/*
Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
и других спецификаций для функционирования компактных приложений на языке
Java (мидлетов) в среде программного обеспечения Малик Эмулятор.
Copyright © 2016, 2019 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package malik.emulator.time;
import java.util.*;
public final class GregorianCalendar extends Calendar
{
private static final byte[][] DAYS;
private static final DateTimeFormat DEFAULT_FORMAT;
private static final DateTimeFormat STANDARD_FORMAT;
static
{
DAYS = new byte[][] {
{
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}, {
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
}
};
DEFAULT_FORMAT = new DefaultFormat();
STANDARD_FORMAT = new StandardFormat();
}
public static boolean isLeapYear(int year)
{
return year % (year % 100 == 0 ? 400 : 4) == 0;
}
public static int getDayOfWeek(int year, int month, int day)
{
return (int) ((((computeTime(year, month, day, 0, 0, 0, 0, 0) + 0x00003883122cd800L) /
86400000L) + 1) % 7);
}
public static int getNumOfDays(int year, int month)
{
return DAYS[isLeapYear(year) ? 1 : 0][month - 1];
}
public static long computeFields(long time, int offset)
{
int year;
int month;
int day;
int hour;
int minute;
int millis;
int dur;
int j;
long i;
byte[] months;
i = (time += ((long) offset) + 0x00003883122cd800L) % 86400000L;
hour = (int) (i / 3600000L);
i %= 3600000L;
minute = (int) (i / 60000L);
i %= 60000L;
millis = (int) i;
i = time / 86400000L;
j = (int) ((i / 146097L) * 400L);
i %= 146097L;
if(i == 146096L)
{
j += 399;
i = 365L;
} else
{
j += (int) ((i / 36524L) * 100L);
i %= 36524L;
j += (int) ((i / 1461L) * 4L);
i %= 1461L;
if(i == 1460)
{
j += 3;
i = 365L;
} else
{
j += (int) (i / 365L);
i %= 365L;
}
}
year = ++j;
months = DAYS[isLeapYear(j) ? 1 : 0];
for(j = 0; i >= (long) (dur = months[j]); j++)
{
i -= (long) dur;
}
month = j + 1;
day = ((int) i) + 1;
return (((long) year) << 48) | (((long) month) << 40) | (((long) day) << 32) |
(((long) hour) << 24) | (((long) minute) << 16) | ((long) millis);
}
public static long computeTime(long fields, int offset)
{
int ms;
return computeTime((int) (fields >>> 48), (byte) (fields >>> 40), (byte) (fields >>> 32),
(byte) (fields >>> 24), (byte) (fields >>> 16),
(ms = ((int) fields) & 0xffff) / 1000, ms % 1000, offset);
}
public static long computeTime(int year, int month, int day,
int hour, int minute, int second, int millis, int offset)
{
int i;
int leap = isLeapYear(year--) ? 1 : 0;
long result = -0x00003883122cd800L;
byte[] months;
result += 12622780800000L * (long) (year / 400);
year %= 400;
result += 3155673600000L * (long) (year / 100);
year %= 100;
result += 126230400000L * (long) (year / 4);
year %= 4;
result += 31536000000L * (long) year;
months = DAYS[leap];
for(i = month - 1; i-- > 0; )
{
result += 86400000L * (long) months[i];
}
return result + (86400000L * (long) (day - 1)) + (3600000L * (long) hour) +
(60000L * (long) minute) + (1000L * (long) second) + ((long) millis) -
(long) offset;
}
public static DateTimeFormat getDefaultFormat()
{
return DEFAULT_FORMAT;
}
public static DateTimeFormat getStandardFormat()
{
return STANDARD_FORMAT;
}
public GregorianCalendar()
{
}
public String toString()
{
return toString(DEFAULT_FORMAT);
}
public String toString(DateTimeFormat format)
{
int[] f;
getTimeInMillis();
computeFields();
return format.represent(1, (f = fields)[YEAR], f[MONTH], f[DAY_OF_MONTH], f[DAY_OF_WEEK],
f[HOUR_OF_DAY], f[MINUTE], f[SECOND], f[MILLISECOND], getTimeZone());
}
protected void computeFields()
{
int dur;
int h;
int j;
long i;
long time;
byte[] months;
int[] f;
i = (time = this.time +
((long) getTimeZone().getRawOffset()) + 0x00003883122cd800L) % 86400000L;
h = (f = fields)[HOUR_OF_DAY] = (int) (i / 3600000L);
f[AM_PM] = h < 12 ? AM : PM;
f[HOUR] = (h %= 12) == 0 ? 12 : h;
i %= 3600000L;
f[MINUTE] = (int) (i / 60000L);
i %= 60000L;
f[SECOND] = (int) (i / 1000L);
i %= 1000L;
f[MILLISECOND] = (int) i;
i = time / 86400000L;
j = (int) ((i / 146097L) * 400L);
i %= 146097L;
if(i == 146096L)
{
j += 399;
i = 365L;
} else
{
j += (int) ((i / 36524L) * 100L);
i %= 36524L;
j += (int) ((i / 1461L) * 4L);
i %= 1461L;
if(i == 1460)
{
j += 3;
i = 365L;
} else
{
j += (int) (i / 365L);
i %= 365L;
}
}
f[YEAR] = ++j;
months = DAYS[isLeapYear(j) ? 1 : 0];
for(j = 0; i >= (long) (dur = months[j]); j++)
{
i -= (long) dur;
}
f[MONTH] = j;
f[DAY_OF_MONTH] = ((int) i) + 1;
f[DAY_OF_WEEK] = ((((int) ((time / 86400000L) % 7L)) + 1) % 7) + 1;
}
protected void computeTime()
{
int[] f = fields;
correctTime();
time = computeTime(f[YEAR], f[MONTH] + 1, f[DAY_OF_MONTH],
f[HOUR_OF_DAY], f[MINUTE], f[SECOND], f[MILLISECOND],
getTimeZone().getRawOffset());
}
private void correctTime()
{
int hour;
int ampm;
boolean[] sets = isSet;
int[] f = fields;
if(sets[HOUR_OF_DAY])
{
f[HOUR_OF_DAY] = hour = Math.abs(f[HOUR_OF_DAY] % 24);
f[AM_PM] = hour < 12 ? AM : PM;
sets[HOUR_OF_DAY] = false;
return;
}
if(sets[AM_PM])
{
if((ampm = f[AM_PM]) != AM && ampm != PM)
{
f[AM_PM] = f[HOUR_OF_DAY] < 12 ? AM : PM;
}
sets[AM_PM] = false;
}
if(sets[HOUR])
{
if((hour = f[HOUR]) > 12)
{
f[HOUR_OF_DAY] = (hour % 12) + 12;
f[HOUR] = hour % 12;
f[AM_PM] = PM;
} else
{
f[HOUR_OF_DAY] = f[AM_PM] == PM ? hour + 12 : hour;
}
sets[HOUR] = false;
}
}
}