170 lines · 5.8 KB · Java
RawDownload
/* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.text; import java.util.Calendar;import static java.util.GregorianCalendar.*; /** * {@code CalendarBuilder} keeps field-value pairs for setting * the calendar fields of the given {@code Calendar}. It has the * {@link Calendar#FIELD_COUNT FIELD_COUNT}-th field for the week year * support. Also {@code ISO_DAY_OF_WEEK} is used to specify * {@code DAY_OF_WEEK} in the ISO day of week numbering. * * <p>{@code CalendarBuilder} retains the semantic of the pseudo * timestamp for fields. {@code CalendarBuilder} uses a single * int array combining fields[] and stamp[] of {@code Calendar}. * * @author Masayoshi Okutsu */class CalendarBuilder {    /*     * Pseudo time stamp constants used in java.util.Calendar     */    private static final int UNSET = 0;    private static final int COMPUTED = 1;    private static final int MINIMUM_USER_STAMP = 2;     private static final int MAX_FIELD = FIELD_COUNT + 1;     public static final int WEEK_YEAR = FIELD_COUNT;    public static final int ISO_DAY_OF_WEEK = 1000; // pseudo field index     // stamp[] (lower half) and field[] (upper half) combined    private final int[] field;    private int nextStamp;    private int maxFieldIndex;     CalendarBuilder() {        field = new int[MAX_FIELD * 2];        nextStamp = MINIMUM_USER_STAMP;        maxFieldIndex = -1;    }     CalendarBuilder set(int index, int value) {        if (index == ISO_DAY_OF_WEEK) {            index = DAY_OF_WEEK;            value = toCalendarDayOfWeek(value);        }        field[index] = nextStamp++;        field[MAX_FIELD + index] = value;        if (index > maxFieldIndex && index < FIELD_COUNT) {            maxFieldIndex = index;        }        return this;    }     CalendarBuilder addYear(int value) {        field[MAX_FIELD + YEAR] += value;        field[MAX_FIELD + WEEK_YEAR] += value;        return this;    }     boolean isSet(int index) {        if (index == ISO_DAY_OF_WEEK) {            index = DAY_OF_WEEK;        }        return field[index] > UNSET;    }     Calendar establish(Calendar cal) {        boolean weekDate = isSet(WEEK_YEAR)                            && field[WEEK_YEAR] > field[YEAR];        if (weekDate && !cal.isWeekDateSupported()) {            // Use YEAR instead            if (!isSet(YEAR)) {                set(YEAR, field[MAX_FIELD + WEEK_YEAR]);            }            weekDate = false;        }         cal.clear();        // Set the fields from the min stamp to the max stamp so that        // the field resolution works in the Calendar.        for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) {            for (int index = 0; index <= maxFieldIndex; index++) {                if (field[index] == stamp) {                    cal.set(index, field[MAX_FIELD + index]);                    break;                }            }        }         if (weekDate) {            int weekOfYear = isSet(WEEK_OF_YEAR) ? field[MAX_FIELD + WEEK_OF_YEAR] : 1;            int dayOfWeek = isSet(DAY_OF_WEEK) ?                                field[MAX_FIELD + DAY_OF_WEEK] : cal.getFirstDayOfWeek();            if (!isValidDayOfWeek(dayOfWeek) && cal.isLenient()) {                if (dayOfWeek >= 8) {                    dayOfWeek--;                    weekOfYear += dayOfWeek / 7;                    dayOfWeek = (dayOfWeek % 7) + 1;                } else {                    while (dayOfWeek <= 0) {                        dayOfWeek += 7;                        weekOfYear--;                    }                }                dayOfWeek = toCalendarDayOfWeek(dayOfWeek);            }            cal.setWeekDate(field[MAX_FIELD + WEEK_YEAR], weekOfYear, dayOfWeek);        }        return cal;    }     public String toString() {        StringBuilder sb = new StringBuilder();        sb.append("CalendarBuilder:[");        for (int i = 0; i < field.length; i++) {            if (isSet(i)) {                sb.append(i).append('=').append(field[MAX_FIELD + i]).append(',');            }        }        int lastIndex = sb.length() - 1;        if (sb.charAt(lastIndex) == ',') {            sb.setLength(lastIndex);        }        sb.append(']');        return sb.toString();    }     static int toISODayOfWeek(int calendarDayOfWeek) {        return calendarDayOfWeek == SUNDAY ? 7 : calendarDayOfWeek - 1;    }     static int toCalendarDayOfWeek(int isoDayOfWeek) {        if (!isValidDayOfWeek(isoDayOfWeek)) {            // adjust later for lenient mode            return isoDayOfWeek;        }        return isoDayOfWeek == 7 ? SUNDAY : isoDayOfWeek + 1;    }     static boolean isValidDayOfWeek(int dayOfWeek) {        return dayOfWeek > 0 && dayOfWeek <= 7;    }}