EMMA Coverage Report (generated Tue Oct 28 00:01:11 GMT 2008)
[all classes][org.joda.time.chrono]

COVERAGE SUMMARY FOR SOURCE FILE [EthiopicChronology.java]

nameclass, %method, %block, %line, %
EthiopicChronology.java100% (1/1)93%  (13/14)86%  (213/247)92%  (52.4/57)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class EthiopicChronology100% (1/1)93%  (13/14)86%  (213/247)92%  (52.4/57)
readResolve (): Object 0%   (0/1)0%   (0/16)0%   (0/2)
getInstance (DateTimeZone, int): EthiopicChronology 100% (1/1)83%  (89/107)87%  (18.4/21)
<static initializer> 100% (1/1)100% (13/13)100% (4/4)
EthiopicChronology (Chronology, Object, int): void 100% (1/1)100% (6/6)100% (2/2)
assemble (AssembledChronology$Fields): void 100% (1/1)100% (38/38)100% (8/8)
calculateFirstDayOfYearMillis (int): long 100% (1/1)100% (36/36)100% (8/8)
getApproxMillisAtEpochDividedByTwo (): long 100% (1/1)100% (2/2)100% (1/1)
getInstance (): EthiopicChronology 100% (1/1)100% (4/4)100% (1/1)
getInstance (DateTimeZone): EthiopicChronology 100% (1/1)100% (4/4)100% (1/1)
getInstanceUTC (): EthiopicChronology 100% (1/1)100% (2/2)100% (1/1)
getMaxYear (): int 100% (1/1)100% (2/2)100% (1/1)
getMinYear (): int 100% (1/1)100% (2/2)100% (1/1)
withUTC (): Chronology 100% (1/1)100% (2/2)100% (1/1)
withZone (DateTimeZone): Chronology 100% (1/1)100% (13/13)100% (5/5)

1/*
2 *  Copyright 2001-2005 Stephen Colebourne
3 *
4 *  Licensed under the Apache License, Version 2.0 (the "License");
5 *  you may not use this file except in compliance with the License.
6 *  You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 *  Unless required by applicable law or agreed to in writing, software
11 *  distributed under the License is distributed on an "AS IS" BASIS,
12 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 *  See the License for the specific language governing permissions and
14 *  limitations under the License.
15 */
16package org.joda.time.chrono;
17 
18import java.util.HashMap;
19import java.util.Map;
20 
21import org.joda.time.Chronology;
22import org.joda.time.DateTime;
23import org.joda.time.DateTimeConstants;
24import org.joda.time.DateTimeField;
25import org.joda.time.DateTimeZone;
26import org.joda.time.field.SkipDateTimeField;
27 
28/**
29 * Implements the Ethiopic calendar system, which defines every fourth year as
30 * leap, much like the Julian calendar. The year is broken down into 12 months,
31 * each 30 days in length. An extra period at the end of the year is either 5
32 * or 6 days in length. In this implementation, it is considered a 13th month.
33 * <p>
34 * Year 1 in the Ethiopic calendar began on August 29, 8 CE (Julian), thus
35 * Ethiopic years do not begin at the same time as Julian years. This chronology
36 * is not proleptic, as it does not allow dates before the first Ethiopic year.
37 * <p>
38 * This implementation defines a day as midnight to midnight exactly as per
39 * the ISO chronology. Some references indicate that a coptic day starts at
40 * sunset on the previous ISO day, but this has not been confirmed and is not
41 * implemented.
42 * <p>
43 * EthiopicChronology is thread-safe and immutable.
44 *
45 * @see <a href="http://en.wikipedia.org/wiki/Ethiopian_calendar">Wikipedia</a>
46 *
47 * @author Brian S O'Neill
48 * @author Stephen Colebourne
49 * @since 1.2
50 */
51public final class EthiopicChronology extends BasicFixedMonthChronology {
52 
53    /** Serialization lock */
54    private static final long serialVersionUID = -5972804258688333942L;
55 
56    /**
57     * Constant value for 'Ethiopean Era', equivalent
58     * to the value returned for AD/CE.
59     */
60    public static final int EE = DateTimeConstants.CE;
61 
62    /** A singleton era field. */
63    private static final DateTimeField ERA_FIELD = new BasicSingleEraDateTimeField("EE");
64 
65    /** The lowest year that can be fully supported. */
66    private static final int MIN_YEAR = -292269337;
67 
68    /** The highest year that can be fully supported. */
69    private static final int MAX_YEAR = 292272984;
70 
71    /** Cache of zone to chronology arrays */
72    private static final Map cCache = new HashMap();
73 
74    /** Singleton instance of a UTC EthiopicChronology */
75    private static final EthiopicChronology INSTANCE_UTC;
76    static {
77        // init after static fields
78        INSTANCE_UTC = getInstance(DateTimeZone.UTC);
79    }
80 
81    //-----------------------------------------------------------------------
82    /**
83     * Gets an instance of the EthiopicChronology.
84     * The time zone of the returned instance is UTC.
85     * 
86     * @return a singleton UTC instance of the chronology
87     */
88    public static EthiopicChronology getInstanceUTC() {
89        return INSTANCE_UTC;
90    }
91 
92    /**
93     * Gets an instance of the EthiopicChronology in the default time zone.
94     * 
95     * @return a chronology in the default time zone
96     */
97    public static EthiopicChronology getInstance() {
98        return getInstance(DateTimeZone.getDefault(), 4);
99    }
100 
101    /**
102     * Gets an instance of the EthiopicChronology in the given time zone.
103     * 
104     * @param zone  the time zone to get the chronology in, null is default
105     * @return a chronology in the specified time zone
106     */
107    public static EthiopicChronology getInstance(DateTimeZone zone) {
108        return getInstance(zone, 4);
109    }
110 
111    /**
112     * Gets an instance of the EthiopicChronology in the given time zone.
113     * 
114     * @param zone  the time zone to get the chronology in, null is default
115     * @param minDaysInFirstWeek  minimum number of days in first week of the year; default is 4
116     * @return a chronology in the specified time zone
117     */
118    public static EthiopicChronology getInstance(DateTimeZone zone, int minDaysInFirstWeek) {
119        if (zone == null) {
120            zone = DateTimeZone.getDefault();
121        }
122        EthiopicChronology chrono;
123        synchronized (cCache) {
124            EthiopicChronology[] chronos = (EthiopicChronology[]) cCache.get(zone);
125            if (chronos == null) {
126                chronos = new EthiopicChronology[7];
127                cCache.put(zone, chronos);
128            }
129            try {
130                chrono = chronos[minDaysInFirstWeek - 1];
131            } catch (ArrayIndexOutOfBoundsException e) {
132                throw new IllegalArgumentException
133                    ("Invalid min days in first week: " + minDaysInFirstWeek);
134            }
135            if (chrono == null) {
136                if (zone == DateTimeZone.UTC) {
137                    // First create without a lower limit.
138                    chrono = new EthiopicChronology(null, null, minDaysInFirstWeek);
139                    // Impose lower limit and make another EthiopicChronology.
140                    DateTime lowerLimit = new DateTime(1, 1, 1, 0, 0, 0, 0, chrono);
141                    chrono = new EthiopicChronology
142                        (LimitChronology.getInstance(chrono, lowerLimit, null),
143                         null, minDaysInFirstWeek);
144                } else {
145                    chrono = getInstance(DateTimeZone.UTC, minDaysInFirstWeek);
146                    chrono = new EthiopicChronology
147                        (ZonedChronology.getInstance(chrono, zone), null, minDaysInFirstWeek);
148                }
149                chronos[minDaysInFirstWeek - 1] = chrono;
150            }
151        }
152        return chrono;
153    }
154 
155    // Constructors and instance variables
156    //-----------------------------------------------------------------------
157    /**
158     * Restricted constructor.
159     */
160    EthiopicChronology(Chronology base, Object param, int minDaysInFirstWeek) {
161        super(base, param, minDaysInFirstWeek);
162    }
163 
164    /**
165     * Serialization singleton.
166     */
167    private Object readResolve() {
168        Chronology base = getBase();
169        return base == null ?
170                getInstance(DateTimeZone.UTC, getMinimumDaysInFirstWeek()) :
171                    getInstance(base.getZone(), getMinimumDaysInFirstWeek());
172    }
173 
174    // Conversion
175    //-----------------------------------------------------------------------
176    /**
177     * Gets the Chronology in the UTC time zone.
178     * 
179     * @return the chronology in UTC
180     */
181    public Chronology withUTC() {
182        return INSTANCE_UTC;
183    }
184 
185    /**
186     * Gets the Chronology in a specific time zone.
187     * 
188     * @param zone  the zone to get the chronology in, null is default
189     * @return the chronology
190     */
191    public Chronology withZone(DateTimeZone zone) {
192        if (zone == null) {
193            zone = DateTimeZone.getDefault();
194        }
195        if (zone == getZone()) {
196            return this;
197        }
198        return getInstance(zone);
199    }
200 
201    //-----------------------------------------------------------------------
202    long calculateFirstDayOfYearMillis(int year) {
203        // Java epoch is 1970-01-01 Gregorian which is 1962-04-23 Ethiopic.
204        // Calculate relative to the nearest leap year and account for the
205        // difference later.
206 
207        int relativeYear = year - 1963;
208        int leapYears;
209        if (relativeYear <= 0) {
210            // Add 3 before shifting right since /4 and >>2 behave differently
211            // on negative numbers.
212            leapYears = (relativeYear + 3) >> 2;
213        } else {
214            leapYears = relativeYear >> 2;
215            // For post 1963 an adjustment is needed as jan1st is before leap day
216            if (!isLeapYear(year)) {
217                leapYears++;
218            }
219        }
220        
221        long millis = (relativeYear * 365L + leapYears)
222            * (long)DateTimeConstants.MILLIS_PER_DAY;
223 
224        // Adjust to account for difference between 1963-01-01 and 1962-04-23.
225 
226        return millis + (365L - 112) * DateTimeConstants.MILLIS_PER_DAY;
227    }
228 
229    //-----------------------------------------------------------------------
230    int getMinYear() {
231        return MIN_YEAR;
232    }
233 
234    //-----------------------------------------------------------------------
235    int getMaxYear() {
236        return MAX_YEAR;
237    }
238 
239    //-----------------------------------------------------------------------
240    long getApproxMillisAtEpochDividedByTwo() {
241        return (1962L * MILLIS_PER_YEAR + 112L * DateTimeConstants.MILLIS_PER_DAY) / 2;
242    }
243 
244    //-----------------------------------------------------------------------
245    protected void assemble(Fields fields) {
246        if (getBase() == null) {
247            super.assemble(fields);
248 
249            // Ethiopic, like Julian, has no year zero.
250            fields.year = new SkipDateTimeField(this, fields.year);
251            fields.weekyear = new SkipDateTimeField(this, fields.weekyear);
252            
253            fields.era = ERA_FIELD;
254            fields.monthOfYear = new BasicMonthOfYearDateTimeField(this, 13);
255            fields.months = fields.monthOfYear.getDurationField();
256        }
257    }
258 
259}

[all classes][org.joda.time.chrono]
EMMA 2.0.5312 (C) Vladimir Roubtsov