Calendar.avt

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

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

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