/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package avt.util;
public final class GregorianCalendar(Calendar)
{
private static final long EPOCH_START = +0x0000000000000000L;
private static int getDaysCount(int year, int month) {
switch(month + 1)
{
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
return 31;
case 4:
case 6:
case 9:
case 11:
return 30;
case 2:
return ++year % (year % 100 == 0 ? 400 : 4) == 0 ? 29 : 28;
}
return 0;
}
public (): this(System.currentTimeInMillis(), System.currentOffsetInMillis()) { }
public (long timeInMillis): this(timeInMillis, System.currentOffsetInMillis()) { }
public (long timeInMillis, int offsetInMillis): super(timeInMillis, offsetInMillis) { computeFields(); }
public (Timestamp timestamp): this(timestamp, System.currentOffsetInMillis()) { }
public (Timestamp timestamp, int offsetInMillis): super(timestamp, offsetInMillis) { computeFields(); }
public GregorianCalendar clone() { return new GregorianCalendar(timeInMillis, offsetInMillis); }
protected void computeFields() {
long time = fldTimeInMillis + offsetInMillis - EPOCH_START;
int rem = (int) (time % 86400000);
int[] content = fldFieldsContent;
content[HOUR_OF_DAY] = rem / 3600000;
content[MINUTE] = (rem %= 3600000) / 60000;
content[SECOND] = (rem %= 60000) / 1000;
content[MILLISECOND] = rem % 1000;
int year = ((rem = (int) (time /= 86400000)) / 146097) * 400;
if((rem %= 146097) >= 146096)
{
year += 399;
rem = 365;
} else
{
year += rem / 36524 * 100 + (rem %= 36524) / 1461 * 4;
if((rem %= 1461) >= 1460)
{
year += 3;
rem = 365;
} else
{
year += rem / 365;
rem %= 365;
}
}
int month = 0;
for(int days; rem >= (days = getDaysCount(year, month)); month++) rem -= days;
content[YEAR] = year + 1;
content[MONTH] = month + 1;
content[DAY_OF_MONTH] = rem + 1;
content[DAY_OF_WEEK] = ((int) time + MONDAY) % 7;
computeHalfdayFields();
}
protected void computeTime() {
boolean[] set = fldFieldsSet;
int[] content = fldFieldsContent;
int yer;
int year = yer = content[YEAR] - 1 & 0xffff;
int month = content[MONTH] - 1;
int day = content[DAY_OF_MONTH] - 1;
int hour = set[HOUR_OF_HALFDAY] | set[HALFDAY] | (set[HOUR_OF_HALFDAY] = set[HALFDAY] = false) ? content[HOUR_OF_HALFDAY] % 12 + content[HALFDAY] * 12 : content[HOUR_OF_DAY];
int minute = content[MINUTE];
int second = content[SECOND];
int millisecond = content[MILLISECOND];
int days = 146097 * (year / 400);
year %= 400;
days += 36524 * (year / 100);
year %= 100;
days += 1461 * (year / 4) + 365 * (year % 4) + day;
for(int mnt = 0; mnt < month; mnt++) days += getDaysCount(yer, mnt);
fldTimeInMillis = (long) days * 86400000 + hour * 3600000 + minute * 60000 + second * 1000 + millisecond - offsetInMillis + EPOCH_START;
}
}