rt/emul/compact/src/main/java/java/text/CalendarBuilder.java
author Jaroslav Tulach <jtulach@netbeans.org>
Thu, 03 Oct 2013 15:40:35 +0200
branchjdk7-b147
changeset 1334 588d5bf7a560
child 1339 8cc04f85a683
permissions -rw-r--r--
Set of JDK classes needed to run javac
     1 /*
     2  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 
    26 package java.text;
    27 
    28 import java.util.Calendar;
    29 import static java.util.GregorianCalendar.*;
    30 
    31 /**
    32  * {@code CalendarBuilder} keeps field-value pairs for setting
    33  * the calendar fields of the given {@code Calendar}. It has the
    34  * {@link Calendar#FIELD_COUNT FIELD_COUNT}-th field for the week year
    35  * support. Also {@code ISO_DAY_OF_WEEK} is used to specify
    36  * {@code DAY_OF_WEEK} in the ISO day of week numbering.
    37  *
    38  * <p>{@code CalendarBuilder} retains the semantic of the pseudo
    39  * timestamp for fields. {@code CalendarBuilder} uses a single
    40  * int array combining fields[] and stamp[] of {@code Calendar}.
    41  *
    42  * @author Masayoshi Okutsu
    43  */
    44 class CalendarBuilder {
    45     /*
    46      * Pseudo time stamp constants used in java.util.Calendar
    47      */
    48     private static final int UNSET = 0;
    49     private static final int COMPUTED = 1;
    50     private static final int MINIMUM_USER_STAMP = 2;
    51 
    52     private static final int MAX_FIELD = FIELD_COUNT + 1;
    53 
    54     public static final int WEEK_YEAR = FIELD_COUNT;
    55     public static final int ISO_DAY_OF_WEEK = 1000; // pseudo field index
    56 
    57     // stamp[] (lower half) and field[] (upper half) combined
    58     private final int[] field;
    59     private int nextStamp;
    60     private int maxFieldIndex;
    61 
    62     CalendarBuilder() {
    63         field = new int[MAX_FIELD * 2];
    64         nextStamp = MINIMUM_USER_STAMP;
    65         maxFieldIndex = -1;
    66     }
    67 
    68     CalendarBuilder set(int index, int value) {
    69         if (index == ISO_DAY_OF_WEEK) {
    70             index = DAY_OF_WEEK;
    71             value = toCalendarDayOfWeek(value);
    72         }
    73         field[index] = nextStamp++;
    74         field[MAX_FIELD + index] = value;
    75         if (index > maxFieldIndex && index < FIELD_COUNT) {
    76             maxFieldIndex = index;
    77         }
    78         return this;
    79     }
    80 
    81     CalendarBuilder addYear(int value) {
    82         field[MAX_FIELD + YEAR] += value;
    83         field[MAX_FIELD + WEEK_YEAR] += value;
    84         return this;
    85     }
    86 
    87     boolean isSet(int index) {
    88         if (index == ISO_DAY_OF_WEEK) {
    89             index = DAY_OF_WEEK;
    90         }
    91         return field[index] > UNSET;
    92     }
    93 
    94     Calendar establish(Calendar cal) {
    95         boolean weekDate = isSet(WEEK_YEAR)
    96                             && field[WEEK_YEAR] > field[YEAR];
    97         if (weekDate && !cal.isWeekDateSupported()) {
    98             // Use YEAR instead
    99             if (!isSet(YEAR)) {
   100                 set(YEAR, field[MAX_FIELD + WEEK_YEAR]);
   101             }
   102             weekDate = false;
   103         }
   104 
   105         cal.clear();
   106         // Set the fields from the min stamp to the max stamp so that
   107         // the field resolution works in the Calendar.
   108         for (int stamp = MINIMUM_USER_STAMP; stamp < nextStamp; stamp++) {
   109             for (int index = 0; index <= maxFieldIndex; index++) {
   110                 if (field[index] == stamp) {
   111                     cal.set(index, field[MAX_FIELD + index]);
   112                     break;
   113                 }
   114             }
   115         }
   116 
   117         if (weekDate) {
   118             int weekOfYear = isSet(WEEK_OF_YEAR) ? field[MAX_FIELD + WEEK_OF_YEAR] : 1;
   119             int dayOfWeek = isSet(DAY_OF_WEEK) ?
   120                                 field[MAX_FIELD + DAY_OF_WEEK] : cal.getFirstDayOfWeek();
   121             if (!isValidDayOfWeek(dayOfWeek) && cal.isLenient()) {
   122                 if (dayOfWeek >= 8) {
   123                     dayOfWeek--;
   124                     weekOfYear += dayOfWeek / 7;
   125                     dayOfWeek = (dayOfWeek % 7) + 1;
   126                 } else {
   127                     while (dayOfWeek <= 0) {
   128                         dayOfWeek += 7;
   129                         weekOfYear--;
   130                     }
   131                 }
   132                 dayOfWeek = toCalendarDayOfWeek(dayOfWeek);
   133             }
   134             cal.setWeekDate(field[MAX_FIELD + WEEK_YEAR], weekOfYear, dayOfWeek);
   135         }
   136         return cal;
   137     }
   138 
   139     public String toString() {
   140         StringBuilder sb = new StringBuilder();
   141         sb.append("CalendarBuilder:[");
   142         for (int i = 0; i < field.length; i++) {
   143             if (isSet(i)) {
   144                 sb.append(i).append('=').append(field[MAX_FIELD + i]).append(',');
   145             }
   146         }
   147         int lastIndex = sb.length() - 1;
   148         if (sb.charAt(lastIndex) == ',') {
   149             sb.setLength(lastIndex);
   150         }
   151         sb.append(']');
   152         return sb.toString();
   153     }
   154 
   155     static int toISODayOfWeek(int calendarDayOfWeek) {
   156         return calendarDayOfWeek == SUNDAY ? 7 : calendarDayOfWeek - 1;
   157     }
   158 
   159     static int toCalendarDayOfWeek(int isoDayOfWeek) {
   160         if (!isValidDayOfWeek(isoDayOfWeek)) {
   161             // adjust later for lenient mode
   162             return isoDayOfWeek;
   163         }
   164         return isoDayOfWeek == 7 ? SUNDAY : isoDayOfWeek + 1;
   165     }
   166 
   167     static boolean isValidDayOfWeek(int dayOfWeek) {
   168         return dayOfWeek > 0 && dayOfWeek <= 7;
   169     }
   170 }