/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package avt.util;
public abstract class Calendar(Object, Cloneable, Comparable)
{
/*<fold field ids>*/
public static final int MILLISECOND = 1;
public static final int SECOND = 2;
public static final int MINUTE = 3;
public static final int HOUR_OF_DAY = 4;
public static final int HOUR_OF_HALFDAY = 5;
public static final int HALFDAY = 6;
public static final int DAY_OF_WEEK = 8;
public static final int DAY_OF_MONTH = 10;
public static final int MONTH = 13;
public static final int YEAR = 14;
protected static final int USER = 16;
/*</fold>*/
/*<fold dayOfWeek values>*/
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
public static final int THURSDAY = 4;
public static final int FRIDAY = 5;
public static final int SATURDAY = 6;
public static final int SUNDAY = 0;
/*</fold>*/
/*<fold month values>*/
public static final int JANUARY = 1;
public static final int FEBRUARY = 2;
public static final int MARCH = 3;
public static final int APRIL = 4;
public static final int MAY = 5;
public static final int JUNE = 6;
public static final int JULY = 7;
public static final int AUGUST = 8;
public static final int SEPTEMBER = 9;
public static final int OCTOBER = 10;
public static final int NOVEMBER = 11;
public static final int DECEMBER = 12;
/*</fold>*/
/*<fold halfday values>*/
public static final int AM = 0;
public static final int PM = 1;
/*</fold>*/
protected long fldTimeInMillis;
protected final boolean[] fldFieldsSet;
protected final int[] fldFieldsContent;
private boolean fldTimeSet;
private int fldOffsetInMillis;
private final int fldFieldsCapacity;
private final long fldHashCode;
protected (): this(System.currentTimeInMillis(), System.currentOffsetInMillis(), USER) { }
protected (long timeInMillis): this(timeInMillis, System.currentOffsetInMillis(), USER) { }
protected (long timeInMillis, int offsetInMillis): this(timeInMillis, offsetInMillis, USER) { }
protected (long timeInMillis, int offsetInMillis, int fieldsCapacity) {
int capacity = fieldsCapacity < USER ? USER : fieldsCapacity;
fldTimeInMillis = timeInMillis;
fldFieldsSet = new boolean[capacity];
fldFieldsContent = new int[capacity];
fldOffsetInMillis = offsetInMillis;
fldFieldsCapacity = capacity;
fldHashCode = timeInMillis;
}
protected (Timestamp timestamp): this(timestamp != null ? timestamp.timeInMillis : System.currentTimeInMillis(), System.currentOffsetInMillis(), USER) { }
protected (Timestamp timestamp, int offsetInMillis): this(timestamp != null ? timestamp.timeInMillis : System.currentTimeInMillis(), offsetInMillis, USER) { }
protected (Timestamp timestamp, int offsetInMillis, int fieldsCapacity): this(timestamp != null ? timestamp.timeInMillis : System.currentTimeInMillis(), offsetInMillis, fieldsCapacity) { }
public abstract Calendar clone();
public boolean equals(Object anot) { return anot == this || anot instanceof Calendar && ((Calendar) anot).getTimeInMillis() == getTimeInMillis(); }
public int hashCode() {
long hash = fldHashCode;
return (int) (hash ^ (hash >> 32));
}
public long hashCodeAsLong() { return fldHashCode; }
public String toString() { return ((Object) (new LocalizedCalendarRepresenter(this))).toString(); }
public int compareTo(Comparable anot) { return anot == this ? EQUALS : !(anot instanceof Calendar) ? INDEFINITE : Long.compare(getTimeInMillis(), ((Calendar) anot).getTimeInMillis()); }
public final void set(int fieldId, int fieldValue) {
if(fieldId >= 0 && fieldId < fldFieldsCapacity)
{
fldTimeSet = false;
fldFieldsSet[fieldId] = true;
fldFieldsContent[fieldId] = fieldValue;
}
}
public final int get(int fieldId) {
switch(fieldId)
{
case HALFDAY:
case DAY_OF_WEEK:
case HOUR_OF_DAY:
case HOUR_OF_HALFDAY:
getTimeInMillis();
computeFields();
break;
default:
if(fieldId >= USER && fieldId < fldFieldsCapacity && isFieldAutoComputable(fieldId))
{
getTimeInMillis();
computeFields();
}
}
return fieldId < 0 || fieldId >= fldFieldsCapacity ? 0 : fldFieldsContent[fieldId];
}
public final int year { index = YEAR, read = get, write = set }
public final int month { index = MONTH, read = get, write = set }
public final int dayOfMonth { index = DAY_OF_MONTH, read = get, write = set }
public final int dayOfWeek { index = DAY_OF_WEEK, read = get, write = set }
public final int halfday { index = HALFDAY, read = get, write = set }
public final int hourOfHalfday { index = HOUR_OF_HALFDAY, read = get, write = set }
public final int hourOfDay { index = HOUR_OF_DAY, read = get, write = set }
public final int minute { index = MINUTE, read = get, write = set }
public final int second { index = SECOND, read = get, write = set }
public final int millisecond { index = MILLISECOND, read = get, write = set }
public final int offsetInMillis { read = fldOffsetInMillis, write = setOffsetInMillis }
public final long timeInMillis { read = getTimeInMillis, write = setTimeInMillis }
public final Timestamp timestamp { read = getTimestamp, write = setTimestamp }
protected abstract void computeTime();
protected abstract void computeFields();
protected void computeHalfdayFields() {
int[] fields = fldFieldsContent;
int hour = fields[HOUR_OF_DAY];
fields[HALFDAY] = hour < 12 ? AM : PM;
fields[HOUR_OF_HALFDAY] = (hour %= 12) == 0 ? 12 : hour;
}
protected boolean isFieldAutoComputable(int fieldId) { return false; }
private void setOffsetInMillis(int newOffsetInMillis) {
fldTimeSet = true;
fldFieldsContent[DAY_OF_WEEK] = -1;
fldOffsetInMillis = newOffsetInMillis;
computeFields();
}
private void setTimeInMillis(long newTimeInMillis) {
fldTimeSet = true;
fldFieldsContent[DAY_OF_WEEK] = -1;
fldTimeInMillis = newTimeInMillis;
computeFields();
}
private void setTimestamp(Timestamp newTimestamp) { setTimeInMillis(newTimestamp != null ? newTimestamp.timeInMillis : System.currentTimeInMillis()); }
private long getTimeInMillis() {
if(!fldTimeSet)
{
fldTimeSet = true;
computeTime();
}
return fldTimeInMillis;
}
private Timestamp getTimestamp() { return new Timestamp(getTimeInMillis()); }
}