151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
2d7928577b0cc656c1c6da16bfe281541fdd435eeJoachim Sauer * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.util.calendar;
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Locale;
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.TimeZone;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The <code>BaseCalendar</code> provides basic calendar calculation
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * functions to support the Julian, Gregorian, and Gregorian-based
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * calendar systems.
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Masayoshi Okutsu
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.5
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic abstract class BaseCalendar extends AbstractCalendar {
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int JANUARY = 1;
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int FEBRUARY = 2;
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int MARCH = 3;
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int APRIL = 4;
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int MAY = 5;
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int JUNE = 6;
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int JULY = 7;
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int AUGUST = 8;
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int SEPTEMBER = 9;
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int OCTOBER = 10;
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int NOVEMBER = 11;
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int DECEMBER = 12;
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // day of week constants
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int SUNDAY = 1;
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int MONDAY = 2;
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int TUESDAY = 3;
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int WEDNESDAY = 4;
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int THURSDAY = 5;
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int FRIDAY = 6;
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int SATURDAY = 7;
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // The base Gregorian year of FIXED_DATES[]
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int BASE_YEAR = 1970;
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Pre-calculated fixed dates of January 1 from BASE_YEAR
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // (Gregorian). This table covers all the years that can be
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // supported by the POSIX time_t (32-bit) after the Epoch. Note
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // that the data type is int[].
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int[] FIXED_DATES = {
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        719163, // 1970
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        719528, // 1971
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        719893, // 1972
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        720259, // 1973
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        720624, // 1974
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        720989, // 1975
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        721354, // 1976
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        721720, // 1977
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        722085, // 1978
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        722450, // 1979
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        722815, // 1980
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        723181, // 1981
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        723546, // 1982
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        723911, // 1983
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        724276, // 1984
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        724642, // 1985
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        725007, // 1986
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        725372, // 1987
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        725737, // 1988
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        726103, // 1989
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        726468, // 1990
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        726833, // 1991
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        727198, // 1992
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        727564, // 1993
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        727929, // 1994
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        728294, // 1995
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        728659, // 1996
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        729025, // 1997
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        729390, // 1998
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        729755, // 1999
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        730120, // 2000
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        730486, // 2001
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        730851, // 2002
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        731216, // 2003
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        731581, // 2004
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        731947, // 2005
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        732312, // 2006
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        732677, // 2007
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        733042, // 2008
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        733408, // 2009
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        733773, // 2010
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        734138, // 2011
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        734503, // 2012
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        734869, // 2013
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        735234, // 2014
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        735599, // 2015
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        735964, // 2016
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        736330, // 2017
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        736695, // 2018
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        737060, // 2019
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        737425, // 2020
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        737791, // 2021
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        738156, // 2022
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        738521, // 2023
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        738886, // 2024
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        739252, // 2025
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        739617, // 2026
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        739982, // 2027
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        740347, // 2028
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        740713, // 2029
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        741078, // 2030
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        741443, // 2031
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        741808, // 2032
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        742174, // 2033
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        742539, // 2034
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        742904, // 2035
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        743269, // 2036
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        743635, // 2037
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        744000, // 2038
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        744365, // 2039
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    };
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public abstract static class Date extends CalendarDate {
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protected Date() {
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            super();
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protected Date(TimeZone zone) {
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            super(zone);
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public Date setNormalizedDate(int normalizedYear, int month, int dayOfMonth) {
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            setNormalizedYear(normalizedYear);
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            setMonth(month).setDayOfMonth(dayOfMonth);
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return this;
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract int getNormalizedYear();
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        public abstract void setNormalizedYear(int normalizedYear);
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Cache for the fixed date of January 1 and year length of the
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // cachedYear. A simple benchmark showed 7% performance
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // improvement with >90% cache hit. The initial values are for Gregorian.
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int cachedYear = 2004;
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long cachedFixedDateJan1 = 731581L;
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long cachedFixedDateNextJan1 = cachedFixedDateJan1 + 366;
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protected final boolean hit(int year) {
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return year == cachedYear;
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protected final boolean hit(long fixedDate) {
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (fixedDate >= cachedFixedDateJan1 &&
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    fixedDate < cachedFixedDateNextJan1);
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protected int getCachedYear() {
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return cachedYear;
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protected long getCachedJan1() {
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return cachedFixedDateJan1;
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        protected void setCache(int year, long jan1, int len) {
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cachedYear = year;
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cachedFixedDateJan1 = jan1;
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cachedFixedDateNextJan1 = jan1 + len;
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean validate(CalendarDate date) {
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Date bdate = (Date) date;
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bdate.isNormalized()) {
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int month = bdate.getMonth();
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (month < JANUARY || month > DECEMBER) {
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int d = bdate.getDayOfMonth();
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (d <= 0 || d > getMonthLength(bdate.getNormalizedYear(), month)) {
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int dow = bdate.getDayOfWeek();
206d7928577b0cc656c1c6da16bfe281541fdd435eeJoachim Sauer        if (dow != Date.FIELD_UNDEFINED && dow != getDayOfWeek(bdate)) {
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!validateTime(date)) {
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bdate.setNormalized(true);
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return true;
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean normalize(CalendarDate date) {
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (date.isNormalized()) {
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Date bdate = (Date) date;
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        TimeZone zi = bdate.getZone();
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // If the date has a time zone, then we need to recalculate
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // the calendar fields. Let getTime() do it.
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (zi != null) {
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            getTime(date);
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int days = normalizeTime(bdate);
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        normalizeMonth(bdate);
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long d = (long)bdate.getDayOfMonth() + days;
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int m = bdate.getMonth();
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int y = bdate.getNormalizedYear();
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int ml = getMonthLength(y, m);
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!(d > 0 && d <= ml)) {
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (d <= 0 && d > -28) {
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ml = getMonthLength(y, --m);
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                d += ml;
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bdate.setDayOfMonth((int) d);
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (m == 0) {
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    m = DECEMBER;
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    bdate.setNormalizedYear(y - 1);
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bdate.setMonth(m);
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else if (d > ml && d < (ml + 28)) {
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                d -= ml;
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                ++m;
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bdate.setDayOfMonth((int)d);
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (m > DECEMBER) {
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    bdate.setNormalizedYear(y + 1);
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    m = JANUARY;
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bdate.setMonth(m);
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                long fixedDate = d + getFixedDate(y, m, 1, bdate) - 1L;
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                getCalendarDateFromFixedDate(bdate, fixedDate);
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bdate.setDayOfWeek(getDayOfWeek(bdate));
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        date.setLeapYear(isLeapYear(bdate.getNormalizedYear()));
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        date.setZoneOffset(0);
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        date.setDaylightSaving(0);
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        bdate.setNormalized(true);
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return true;
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    void normalizeMonth(CalendarDate date) {
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Date bdate = (Date) date;
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int year = bdate.getNormalizedYear();
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long month = bdate.getMonth();
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (month <= 0) {
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long xm = 1L - month;
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            year -= (int)((xm / 12) + 1);
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            month = 13 - (xm % 12);
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bdate.setNormalizedYear(year);
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bdate.setMonth((int) month);
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (month > DECEMBER) {
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            year += (int)((month - 1) / 12);
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            month = ((month - 1)) % 12 + 1;
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bdate.setNormalizedYear(year);
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            bdate.setMonth((int) month);
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns 366 if the specified date is in a leap year, or 365
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * otherwise This method does not perform the normalization with
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the specified <code>CalendarDate</code>. The
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>CalendarDate</code> must be normalized to get a correct
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * value.
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param a <code>CalendarDate</code>
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a year length in days
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @throws ClassCastException if the specified date is not a
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link BaseCalendar.Date}
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getYearLength(CalendarDate date) {
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return isLeapYear(((Date)date).getNormalizedYear()) ? 366 : 365;
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getYearLengthInMonths(CalendarDate date) {
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return 12;
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final int[] DAYS_IN_MONTH
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        //  12   1   2   3   4   5   6   7   8   9  10  11  12
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        = { 31, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final int[] ACCUMULATED_DAYS_IN_MONTH
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        //  12/1 1/1 2/1 3/1 4/1 5/1 6/1 7/1 8/1 9/1 10/1 11/1 12/1
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        = {  -30,  0, 31, 59, 90,120,151,181,212,243, 273, 304, 334};
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final int[] ACCUMULATED_DAYS_IN_MONTH_LEAP
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        //  12/1 1/1 2/1   3/1   4/1   5/1   6/1   7/1   8/1   9/1   10/1   11/1   12/1
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        = {  -30,  0, 31, 59+1, 90+1,120+1,151+1,181+1,212+1,243+1, 273+1, 304+1, 334+1};
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getMonthLength(CalendarDate date) {
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Date gdate = (Date) date;
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int month = gdate.getMonth();
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (month < JANUARY || month > DECEMBER) {
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("Illegal month value: " + month);
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getMonthLength(gdate.getNormalizedYear(), month);
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // accepts 0 (December in the previous year) to 12.
332d7928577b0cc656c1c6da16bfe281541fdd435eeJoachim Sauer    private int getMonthLength(int year, int month) {
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int days = DAYS_IN_MONTH[month];
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (month == FEBRUARY && isLeapYear(year)) {
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            days++;
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return days;
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public long getDayOfYear(CalendarDate date) {
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getDayOfYear(((Date)date).getNormalizedYear(),
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            date.getMonth(),
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            date.getDayOfMonth());
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    final long getDayOfYear(int year, int month, int dayOfMonth) {
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (long) dayOfMonth
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            + (isLeapYear(year) ?
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski               ACCUMULATED_DAYS_IN_MONTH_LEAP[month] : ACCUMULATED_DAYS_IN_MONTH[month]);
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // protected
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public long getFixedDate(CalendarDate date) {
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!date.isNormalized()) {
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            normalizeMonth(date);
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getFixedDate(((Date)date).getNormalizedYear(),
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            date.getMonth(),
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            date.getDayOfMonth(),
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            (BaseCalendar.Date) date);
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // public for java.util.GregorianCalendar
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public long getFixedDate(int year, int month, int dayOfMonth, BaseCalendar.Date cache) {
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isJan1 = month == JANUARY && dayOfMonth == 1;
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Look up the one year cache
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cache != null && cache.hit(year)) {
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (isJan1) {
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return cache.getCachedJan1();
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return cache.getCachedJan1() + getDayOfYear(year, month, dayOfMonth) - 1;
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Look up the pre-calculated fixed date table
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int n = year - BASE_YEAR;
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (n >= 0 && n < FIXED_DATES.length) {
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            long jan1 = FIXED_DATES[n];
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (cache != null) {
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                cache.setCache(year, jan1, isLeapYear(year) ? 366 : 365);
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return isJan1 ? jan1 : jan1 + getDayOfYear(year, month, dayOfMonth) - 1;
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long prevyear = (long)year - 1;
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long days = dayOfMonth;
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (prevyear >= 0) {
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            days += (365 * prevyear)
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   + (prevyear / 4)
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   - (prevyear / 100)
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   + (prevyear / 400)
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   + ((367 * month - 362) / 12);
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            days += (365 * prevyear)
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   + CalendarUtils.floorDivide(prevyear, 4)
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   - CalendarUtils.floorDivide(prevyear, 100)
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   + CalendarUtils.floorDivide(prevyear, 400)
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   + CalendarUtils.floorDivide((367 * month - 362), 12);
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (month > FEBRUARY) {
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            days -=  isLeapYear(year) ? 1 : 2;
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // If it's January 1, update the cache.
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (cache != null && isJan1) {
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cache.setCache(year, days, isLeapYear(year) ? 366 : 365);
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return days;
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Calculates calendar fields and store them in the specified
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>CalendarDate</code>.
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // should be 'protected'
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void getCalendarDateFromFixedDate(CalendarDate date,
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                             long fixedDate) {
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Date gdate = (Date) date;
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int year;
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long jan1;
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean isLeap;
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (gdate.hit(fixedDate)) {
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            year = gdate.getCachedYear();
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            jan1 = gdate.getCachedJan1();
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            isLeap = isLeapYear(year);
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Looking up FIXED_DATES[] here didn't improve performance
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // much. So we calculate year and jan1. getFixedDate()
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // will look up FIXED_DATES[] actually.
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            year = getGregorianYearFromFixedDate(fixedDate);
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            jan1 = getFixedDate(year, JANUARY, 1, null);
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            isLeap = isLeapYear(year);
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Update the cache data
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            gdate.setCache (year, jan1, isLeap ? 366 : 365);
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int priorDays = (int)(fixedDate - jan1);
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long mar1 = jan1 + 31 + 28;
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (isLeap) {
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ++mar1;
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (fixedDate >= mar1) {
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            priorDays += isLeap ? 1 : 2;
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int month = 12 * priorDays + 373;
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (month > 0) {
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            month /= 367;
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            month = CalendarUtils.floorDivide(month, 367);
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long month1 = jan1 + ACCUMULATED_DAYS_IN_MONTH[month];
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (isLeap && month >= MARCH) {
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ++month1;
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int dayOfMonth = (int)(fixedDate - month1) + 1;
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int dayOfWeek = getDayOfWeekFromFixedDate(fixedDate);
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        assert dayOfWeek > 0 : "negative day of week " + dayOfWeek;
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        gdate.setNormalizedYear(year);
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        gdate.setMonth(month);
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        gdate.setDayOfMonth(dayOfMonth);
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        gdate.setDayOfWeek(dayOfWeek);
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        gdate.setLeapYear(isLeap);
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        gdate.setNormalized(true);
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the day of week of the given Gregorian date.
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getDayOfWeek(CalendarDate date) {
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long fixedDate = getFixedDate(date);
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getDayOfWeekFromFixedDate(fixedDate);
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public static final int getDayOfWeekFromFixedDate(long fixedDate) {
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // The fixed day 1 (January 1, 1 Gregorian) is Monday.
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (fixedDate >= 0) {
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (int)(fixedDate % 7) + SUNDAY;
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (int)CalendarUtils.mod(fixedDate, 7) + SUNDAY;
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int getYearFromFixedDate(long fixedDate) {
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return getGregorianYearFromFixedDate(fixedDate);
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the Gregorian year number of the given fixed date.
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    final int getGregorianYearFromFixedDate(long fixedDate) {
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        long d0;
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int  d1, d2, d3, d4;
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int  n400, n100, n4, n1;
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int  year;
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (fixedDate > 0) {
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d0 = fixedDate - 1;
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n400 = (int)(d0 / 146097);
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d1 = (int)(d0 % 146097);
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n100 = d1 / 36524;
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d2 = d1 % 36524;
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n4 = d2 / 1461;
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d3 = d2 % 1461;
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n1 = d3 / 365;
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d4 = (d3 % 365) + 1;
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d0 = fixedDate - 1;
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n400 = (int)CalendarUtils.floorDivide(d0, 146097L);
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d1 = (int)CalendarUtils.mod(d0, 146097L);
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n100 = CalendarUtils.floorDivide(d1, 36524);
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d2 = CalendarUtils.mod(d1, 36524);
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n4 = CalendarUtils.floorDivide(d2, 1461);
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d3 = CalendarUtils.mod(d2, 1461);
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            n1 = CalendarUtils.floorDivide(d3, 365);
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            d4 = CalendarUtils.mod(d3, 365) + 1;
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!(n100 == 4 || n1 == 4)) {
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ++year;
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return year;
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return true if the specified year is a Gregorian leap year, or
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * false otherwise.
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see BaseCalendar#isGregorianLeapYear
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    protected boolean isLeapYear(CalendarDate date) {
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return isLeapYear(((Date)date).getNormalizedYear());
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    boolean isLeapYear(int normalizedYear) {
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return CalendarUtils.isGregorianLeapYear(normalizedYear);
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
539