/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024, 2026 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package avt.util;
public abstract class Calendar(Object, Cloneable)
{
/*<fold значения поля dayOfWeek>*/
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>*/
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>*/
public static final int AM = 0;
public static final int PM = 1;
/*</fold>*/
/*<fold ИД полей>*/
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>*/
protected long fldTimeInMillis;
protected final boolean[] fldFieldsSet;
protected final int[] fldFieldsContent;
private boolean fldTimeSet;
private int fldOffsetInMillis;
private final int fldFieldsCapacity;
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;
}
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 String toString() { return ((Object) (new LocalizedCalendarRepresenter(this))).toString(); }
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) {
int fieldsCapacity = fldFieldsCapacity;
switch(fieldId)
{
default:
{
if(fieldId < USER || fieldId >= fieldsCapacity || !isFieldAutoComputable(fieldId)) break;
/* падение через */
}
case HALFDAY:
case DAY_OF_WEEK:
case HOUR_OF_DAY:
case HOUR_OF_HALFDAY:
{
getTimeInMillis();
computeFields();
}
}
return fieldId < 0 || fieldId >= fieldsCapacity ? 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()); }
}