jdk/src/share/classes/java/time/calendar/HijrahDate.java
author dsamersoff
Tue, 12 Feb 2013 16:02:14 +0400
changeset 15657 c588664d547e
parent 15289 3ac550392e43
permissions -rw-r--r--
8007786: JDK-8002048 testcase doesn't work on Solaris Summary: test built in into Solaris shell doesn't have -e operator Reviewed-by: sla, sspitsyn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
15289
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     1
/*
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     2
 * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     4
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    10
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    15
 * accompanied this code).
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    16
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    20
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    23
 * questions.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    24
 */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    25
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    26
/*
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    27
 * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    28
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    29
 * All rights reserved.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    30
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    31
 * Redistribution and use in source and binary forms, with or without
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    32
 * modification, are permitted provided that the following conditions are met:
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    33
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    34
 *  * Redistributions of source code must retain the above copyright notice,
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    35
 *    this list of conditions and the following disclaimer.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    36
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    37
 *  * Redistributions in binary form must reproduce the above copyright notice,
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    38
 *    this list of conditions and the following disclaimer in the documentation
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    39
 *    and/or other materials provided with the distribution.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    40
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    41
 *  * Neither the name of JSR-310 nor the names of its contributors
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    42
 *    may be used to endorse or promote products derived from this software
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    43
 *    without specific prior written permission.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    44
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    45
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    46
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    47
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    48
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    49
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    50
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    51
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    52
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    53
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    54
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    55
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    56
 */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    57
package java.time.calendar;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    58
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    59
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    60
import static java.time.temporal.ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    61
import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_MONTH;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    62
import static java.time.temporal.ChronoField.ALIGNED_WEEK_OF_YEAR;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    63
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    64
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    65
import static java.time.temporal.ChronoField.YEAR;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    66
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    67
import java.io.IOException;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    68
import java.io.ObjectInput;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    69
import java.io.ObjectOutput;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    70
import java.io.Serializable;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    71
import java.time.DateTimeException;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    72
import java.time.DayOfWeek;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    73
import java.time.LocalDate;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    74
import java.time.temporal.ChronoField;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    75
import java.time.temporal.ChronoLocalDate;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    76
import java.time.temporal.TemporalField;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    77
import java.time.temporal.ValueRange;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    78
import java.util.Objects;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    79
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    80
/**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    81
 * A date in the Hijrah calendar system.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    82
 * <p>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    83
 * This implements {@code ChronoLocalDate} for the {@link HijrahChrono Hijrah calendar}.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    84
 * <p>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    85
 * The Hijrah calendar has a different total of days in a year than
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    86
 * Gregorian calendar, and a month is based on the period of a complete
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    87
 * revolution of the moon around the earth (as between successive new moons).
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    88
 * The calendar cycles becomes longer and unstable, and sometimes a manual
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    89
 * adjustment (for entering deviation) is necessary for correctness
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    90
 * because of the complex algorithm.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    91
 * <p>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    92
 * HijrahDate supports the manual adjustment feature by providing a configuration
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    93
 * file. The configuration file contains the adjustment (deviation) data with following format.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    94
 * <pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    95
 *   StartYear/StartMonth(0-based)-EndYear/EndMonth(0-based):Deviation day (1, 2, -1, or -2)
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    96
 *   Line separator or ";" is used for the separator of each deviation data.</pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    97
 *   Here is the example.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    98
 * <pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
    99
 *     1429/0-1429/1:1
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   100
 *     1429/2-1429/7:1;1429/6-1429/11:1
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   101
 *     1429/11-9999/11:1</pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   102
 * The default location of the configuration file is:
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   103
 * <pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   104
 *   $CLASSPATH/java/time/i18n</pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   105
 * And the default file name is:
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   106
 * <pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   107
 *   hijrah_deviation.cfg</pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   108
 * The default location and file name can be overriden by setting
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   109
 * following two Java's system property.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   110
 * <pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   111
 *   Location: java.time.i18n.HijrahDate.deviationConfigDir
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   112
 *   File name: java.time.i18n.HijrahDate.deviationConfigFile</pre>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   113
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   114
 * <h3>Specification for implementors</h3>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   115
 * This class is immutable and thread-safe.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   116
 *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   117
 * @since 1.8
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   118
 */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   119
final class HijrahDate
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   120
        extends ChronoDateImpl<HijrahChrono>
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   121
        implements ChronoLocalDate<HijrahChrono>, Serializable {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   122
    // this class is package-scoped so that future conversion to public
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   123
    // would not change serialization
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   124
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   125
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   126
     * Serialization version.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   127
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   128
    private static final long serialVersionUID = -5207853542612002020L;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   129
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   130
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   131
     * The Chronology of this HijrahDate.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   132
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   133
    private final HijrahChrono chrono;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   134
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   135
     * The era.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   136
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   137
    private final transient HijrahEra era;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   138
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   139
     * The year.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   140
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   141
    private final transient int yearOfEra;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   142
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   143
     * The month-of-year.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   144
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   145
    private final transient int monthOfYear;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   146
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   147
     * The day-of-month.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   148
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   149
    private final transient int dayOfMonth;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   150
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   151
     * The day-of-year.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   152
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   153
    private final transient int dayOfYear;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   154
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   155
     * The day-of-week.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   156
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   157
    private final transient DayOfWeek dayOfWeek;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   158
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   159
     * Gregorian days for this object. Holding number of days since 1970/01/01.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   160
     * The number of days are calculated with pure Gregorian calendar
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   161
     * based.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   162
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   163
    private final long gregorianEpochDay;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   164
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   165
     * True if year is leap year.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   166
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   167
    private final transient boolean isLeapYear;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   168
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   169
    //-------------------------------------------------------------------------
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   170
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   171
     * Obtains an instance of {@code HijrahDate} from the Hijrah era year,
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   172
     * month-of-year and day-of-month. This uses the Hijrah era.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   173
     *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   174
     * @param prolepticYear  the proleptic year to represent in the Hijrah
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   175
     * @param monthOfYear  the month-of-year to represent, from 1 to 12
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   176
     * @param dayOfMonth  the day-of-month to represent, from 1 to 30
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   177
     * @return the Hijrah date, never null
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   178
     * @throws DateTimeException if the value of any field is out of range
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   179
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   180
    static HijrahDate of(HijrahChrono chrono, int prolepticYear, int monthOfYear, int dayOfMonth) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   181
        return (prolepticYear >= 1) ?
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   182
            HijrahDate.of(chrono, HijrahEra.AH, prolepticYear, monthOfYear, dayOfMonth) :
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   183
            HijrahDate.of(chrono, HijrahEra.BEFORE_AH, 1 - prolepticYear, monthOfYear, dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   184
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   185
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   186
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   187
     * Obtains an instance of {@code HijrahDate} from the era, year-of-era
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   188
     * month-of-year and day-of-month.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   189
     *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   190
     * @param era  the era to represent, not null
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   191
     * @param yearOfEra  the year-of-era to represent, from 1 to 9999
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   192
     * @param monthOfYear  the month-of-year to represent, from 1 to 12
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   193
     * @param dayOfMonth  the day-of-month to represent, from 1 to 31
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   194
     * @return the Hijrah date, never null
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   195
     * @throws DateTimeException if the value of any field is out of range
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   196
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   197
    private static HijrahDate of(HijrahChrono chrono, HijrahEra era, int yearOfEra, int monthOfYear, int dayOfMonth) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   198
        Objects.requireNonNull(era, "era");
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   199
        chrono.checkValidYearOfEra(yearOfEra);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   200
        chrono.checkValidMonth(monthOfYear);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   201
        chrono.checkValidDayOfMonth(dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   202
        long gregorianDays = chrono.getGregorianEpochDay(era.prolepticYear(yearOfEra), monthOfYear, dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   203
        return new HijrahDate(chrono, gregorianDays);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   204
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   205
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   206
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   207
     * Obtains an instance of {@code HijrahDate} from a date.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   208
     *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   209
     * @param date  the date to use, not null
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   210
     * @return the Hijrah date, never null
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   211
     * @throws DateTimeException if the year is invalid
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   212
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   213
    private static HijrahDate of(HijrahChrono chrono, LocalDate date) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   214
        long gregorianDays = date.toEpochDay();
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   215
        return new HijrahDate(chrono, gregorianDays);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   216
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   217
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   218
    static HijrahDate ofEpochDay(HijrahChrono chrono, long epochDay) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   219
        return new HijrahDate(chrono, epochDay);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   220
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   221
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   222
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   223
     * Constructs an instance with the specified date.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   224
     *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   225
     * @param gregorianDay  the number of days from 0001/01/01 (Gregorian), caller calculated
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   226
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   227
    private HijrahDate(HijrahChrono chrono, long gregorianDay) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   228
        this.chrono = chrono;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   229
        int[] dateInfo = chrono.getHijrahDateInfo(gregorianDay);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   230
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   231
        chrono.checkValidYearOfEra(dateInfo[1]);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   232
        chrono.checkValidMonth(dateInfo[2]);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   233
        chrono.checkValidDayOfMonth(dateInfo[3]);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   234
        chrono.checkValidDayOfYear(dateInfo[4]);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   235
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   236
        this.era = HijrahEra.of(dateInfo[0]);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   237
        this.yearOfEra = dateInfo[1];
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   238
        this.monthOfYear = dateInfo[2];
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   239
        this.dayOfMonth = dateInfo[3];
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   240
        this.dayOfYear = dateInfo[4];
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   241
        this.dayOfWeek = DayOfWeek.of(dateInfo[5]);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   242
        this.gregorianEpochDay = gregorianDay;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   243
        this.isLeapYear = chrono.isLeapYear(this.yearOfEra);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   244
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   245
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   246
    //-----------------------------------------------------------------------
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   247
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   248
    public HijrahChrono getChrono() {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   249
        return chrono;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   250
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   251
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   252
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   253
    public ValueRange range(TemporalField field) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   254
        if (field instanceof ChronoField) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   255
            if (isSupported(field)) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   256
                ChronoField f = (ChronoField) field;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   257
                switch (f) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   258
                    case DAY_OF_MONTH: return ValueRange.of(1, lengthOfMonth());
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   259
                    case DAY_OF_YEAR: return ValueRange.of(1, lengthOfYear());
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   260
                    case ALIGNED_WEEK_OF_MONTH: return ValueRange.of(1, 5);  // TODO
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   261
                    case YEAR_OF_ERA: return ValueRange.of(1, 1000);  // TODO
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   262
                }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   263
                return getChrono().range(f);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   264
            }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   265
            throw new DateTimeException("Unsupported field: " + field.getName());
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   266
        }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   267
        return field.doRange(this);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   268
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   269
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   270
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   271
    public long getLong(TemporalField field) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   272
        if (field instanceof ChronoField) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   273
            switch ((ChronoField) field) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   274
                case DAY_OF_WEEK: return dayOfWeek.getValue();
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   275
                case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((dayOfWeek.getValue() - 1) % 7) + 1;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   276
                case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((dayOfYear - 1) % 7) + 1;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   277
                case DAY_OF_MONTH: return this.dayOfMonth;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   278
                case DAY_OF_YEAR: return this.dayOfYear;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   279
                case EPOCH_DAY: return toEpochDay();
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   280
                case ALIGNED_WEEK_OF_MONTH: return ((dayOfMonth - 1) / 7) + 1;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   281
                case ALIGNED_WEEK_OF_YEAR: return ((dayOfYear - 1) / 7) + 1;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   282
                case MONTH_OF_YEAR: return monthOfYear;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   283
                case YEAR_OF_ERA: return yearOfEra;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   284
                case YEAR: return yearOfEra;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   285
                case ERA: return era.getValue();
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   286
            }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   287
            throw new DateTimeException("Unsupported field: " + field.getName());
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   288
        }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   289
        return field.doGet(this);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   290
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   291
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   292
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   293
    public HijrahDate with(TemporalField field, long newValue) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   294
        if (field instanceof ChronoField) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   295
            ChronoField f = (ChronoField) field;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   296
            f.checkValidValue(newValue);        // TODO: validate value
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   297
            int nvalue = (int) newValue;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   298
            switch (f) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   299
                case DAY_OF_WEEK: return plusDays(newValue - dayOfWeek.getValue());
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   300
                case ALIGNED_DAY_OF_WEEK_IN_MONTH: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_MONTH));
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   301
                case ALIGNED_DAY_OF_WEEK_IN_YEAR: return plusDays(newValue - getLong(ALIGNED_DAY_OF_WEEK_IN_YEAR));
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   302
                case DAY_OF_MONTH: return resolvePreviousValid(yearOfEra, monthOfYear, nvalue);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   303
                case DAY_OF_YEAR: return resolvePreviousValid(yearOfEra, ((nvalue - 1) / 30) + 1, ((nvalue - 1) % 30) + 1);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   304
                case EPOCH_DAY: return new HijrahDate(chrono, nvalue);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   305
                case ALIGNED_WEEK_OF_MONTH: return plusDays((newValue - getLong(ALIGNED_WEEK_OF_MONTH)) * 7);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   306
                case ALIGNED_WEEK_OF_YEAR: return plusDays((newValue - getLong(ALIGNED_WEEK_OF_YEAR)) * 7);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   307
                case MONTH_OF_YEAR: return resolvePreviousValid(yearOfEra, nvalue, dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   308
                case YEAR_OF_ERA: return resolvePreviousValid(yearOfEra >= 1 ? nvalue : 1 - nvalue, monthOfYear, dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   309
                case YEAR: return resolvePreviousValid(nvalue, monthOfYear, dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   310
                case ERA: return resolvePreviousValid(1 - yearOfEra, monthOfYear, dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   311
            }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   312
            throw new DateTimeException("Unsupported field: " + field.getName());
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   313
        }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   314
        return (HijrahDate) ChronoLocalDate.super.with(field, newValue);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   315
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   316
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   317
    private HijrahDate resolvePreviousValid(int yearOfEra, int month, int day) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   318
        int monthDays = getMonthDays(month - 1, yearOfEra);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   319
        if (day > monthDays) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   320
            day = monthDays;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   321
        }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   322
        return HijrahDate.of(chrono, yearOfEra, month, day);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   323
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   324
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   325
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   326
    public long toEpochDay() {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   327
         return chrono.getGregorianEpochDay(yearOfEra, monthOfYear, dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   328
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   329
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   330
    //-----------------------------------------------------------------------
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   331
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   332
    public HijrahEra getEra() {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   333
        return this.era;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   334
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   335
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   336
    //-----------------------------------------------------------------------
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   337
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   338
     * Checks if the year is a leap year, according to the Hijrah calendar system rules.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   339
     *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   340
     * @return true if this date is in a leap year
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   341
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   342
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   343
    public boolean isLeapYear() {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   344
        return this.isLeapYear;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   345
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   346
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   347
    //-----------------------------------------------------------------------
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   348
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   349
    public HijrahDate plusYears(long years) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   350
        if (years == 0) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   351
            return this;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   352
        }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   353
        int newYear = Math.addExact(this.yearOfEra, (int)years);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   354
        return HijrahDate.of(chrono, this.era, newYear, this.monthOfYear, this.dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   355
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   356
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   357
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   358
    public HijrahDate plusMonths(long months) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   359
        if (months == 0) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   360
            return this;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   361
        }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   362
        int newMonth = this.monthOfYear - 1;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   363
        newMonth = newMonth + (int)months;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   364
        int years = newMonth / 12;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   365
        newMonth = newMonth % 12;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   366
        while (newMonth < 0) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   367
            newMonth += 12;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   368
            years = Math.subtractExact(years, 1);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   369
        }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   370
        int newYear = Math.addExact(this.yearOfEra, years);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   371
        return HijrahDate.of(chrono, this.era, newYear, newMonth + 1, this.dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   372
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   373
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   374
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   375
    public HijrahDate plusDays(long days) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   376
        return new HijrahDate(chrono, this.gregorianEpochDay + days);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   377
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   378
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   379
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   380
     * Returns month days from the beginning of year.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   381
     *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   382
     * @param month  month (0-based)
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   383
     * @parma year  year
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   384
     * @return month days from the beginning of year
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   385
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   386
    private int getMonthDays(int month, int year) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   387
        int[] newMonths = chrono.getAdjustedMonthDays(year);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   388
        return newMonths[month];
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   389
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   390
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   391
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   392
     * Returns month length.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   393
     *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   394
     * @param month  month (0-based)
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   395
     * @param year  year
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   396
     * @return month length
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   397
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   398
    private int getMonthLength(int month, int year) {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   399
      int[] newMonths = chrono.getAdjustedMonthLength(year);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   400
      return newMonths[month];
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   401
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   402
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   403
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   404
    public int lengthOfMonth() {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   405
        return getMonthLength(monthOfYear - 1, yearOfEra);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   406
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   407
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   408
    @Override
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   409
    public int lengthOfYear() {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   410
        return chrono.getYearLength(yearOfEra);  // TODO: proleptic year
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   411
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   412
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   413
    //-----------------------------------------------------------------------
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   414
    private Object writeReplace() {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   415
        return new Ser(Ser.HIJRAH_DATE_TYPE, this);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   416
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   417
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   418
    void writeExternal(ObjectOutput out) throws IOException {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   419
        // HijrahChrono is implicit in the Hijrah_DATE_TYPE
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   420
        out.writeObject(chrono);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   421
        out.writeInt(get(YEAR));
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   422
        out.writeByte(get(MONTH_OF_YEAR));
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   423
        out.writeByte(get(DAY_OF_MONTH));
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   424
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   425
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   426
    /**
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   427
     * Replaces the date instance from the stream with a valid one.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   428
     * ReadExternal has already read the fields and created a new instance
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   429
     * from the data.
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   430
     *
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   431
     * @return the resolved date, never null
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   432
     */
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   433
    private Object readResolve() {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   434
        return this;
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   435
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   436
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   437
    static ChronoLocalDate<HijrahChrono> readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   438
        HijrahChrono chrono = (HijrahChrono)in.readObject();
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   439
        int year = in.readInt();
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   440
        int month = in.readByte();
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   441
        int dayOfMonth = in.readByte();
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   442
        return chrono.date(year, month, dayOfMonth);
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   443
    }
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   444
3ac550392e43 8003680: JSR 310 Date/Time API
sherman
parents:
diff changeset
   445
}