GregorianCalendar.avt

Переключить прокрутку окна
Загрузить этот исходный код

/*
    Реализация среды исполнения языка программирования
    Объектно-ориентированный продвинутый векторный транслятор

    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;
    }
}