001: /*
002: * Copyright 2001-2005 Stephen Colebourne
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.joda.time.chrono.gj;
017:
018: import org.joda.time.DateTimeField;
019:
020: /**
021: * A reference Julian chronology implementation, intended for testing purposes
022: * only. Correctness is favored over performance. The key functions for date
023: * calculations are based on ones provided in "Calendrical Calculations", ISBN
024: * 0-521-77752-6.
025: *
026: * @author Brian S O'Neill
027: */
028: public final class TestJulianChronology extends TestGJChronology {
029:
030: private static final long JULIAN_EPOCH;
031:
032: static {
033: // Constant as defined in book.
034: JULIAN_EPOCH = new TestGregorianChronology().fixedFromGJ(0, 12,
035: 30);
036: }
037:
038: /**
039: * Constructs with an epoch of 1969-12-19.
040: */
041: public TestJulianChronology() {
042: super (1969, 12, 19);
043: }
044:
045: public TestJulianChronology(int epochYear, int epochMonth,
046: int epochDay) {
047: super (epochYear, epochMonth, epochDay);
048: }
049:
050: public DateTimeField dayOfMonth() {
051: return new TestJulianDayOfMonthField(this );
052: }
053:
054: public DateTimeField weekyear() {
055: return new TestJulianWeekyearField(this );
056: }
057:
058: public DateTimeField monthOfYear() {
059: return new TestJulianMonthOfYearField(this );
060: }
061:
062: public DateTimeField year() {
063: return new TestJulianYearField(this );
064: }
065:
066: public String toString() {
067: return "TestJulianChronology";
068: }
069:
070: long millisPerYear() {
071: return (long) (365.25 * MILLIS_PER_DAY);
072: }
073:
074: long millisPerMonth() {
075: return (long) (365.25 * MILLIS_PER_DAY / 12);
076: }
077:
078: boolean isLeapYear(int year) {
079: if (year == 0) {
080: throw new IllegalArgumentException("Illegal year: " + year);
081: }
082: return mod(year, 4) == (year > 0 ? 0 : 3);
083: }
084:
085: /**
086: * @return days from 0001-01-01
087: */
088: long fixedFromGJ(int year, int monthOfYear, int dayOfMonth) {
089: if (year == 0) {
090: throw new IllegalArgumentException("Illegal year: " + year);
091: }
092: int y = (year < 0) ? year + 1 : year;
093: long y_m1 = y - 1;
094: long f = JULIAN_EPOCH - 1 + 365 * y_m1 + div(y_m1, 4)
095: + div(367 * monthOfYear - 362, 12) + dayOfMonth;
096: if (monthOfYear > 2) {
097: f += isLeapYear(year) ? -1 : -2;
098: }
099: return f;
100: }
101:
102: /**
103: * @param date days from 0001-01-01
104: * @return gj year
105: */
106: int gjYearFromFixed(long date) {
107: return gjFromFixed(date)[0];
108: }
109:
110: /**
111: * @param date days from 0001-01-01
112: * @return gj year, monthOfYear, dayOfMonth
113: */
114: int[] gjFromFixed(long date) {
115: long approx = div(4 * (date - JULIAN_EPOCH) + 1464, 1461);
116: long year = (approx <= 0) ? approx - 1 : approx;
117: int year_i = (int) year;
118: if (year_i != year) {
119: throw new RuntimeException(
120: "year cannot be cast to an int: " + year);
121: }
122: long priorDays = date - fixedFromGJ(year_i, 1, 1);
123: long correction;
124: if (date < fixedFromGJ(year_i, 3, 1)) {
125: correction = 0;
126: } else if (isLeapYear(year_i)) {
127: correction = 1;
128: } else {
129: correction = 2;
130: }
131: int monthOfYear = (int) div(
132: 12 * (priorDays + correction) + 373, 367);
133: int day = (int) (date - fixedFromGJ(year_i, monthOfYear, 1) + 1);
134:
135: return new int[] { year_i, monthOfYear, day };
136: }
137:
138: long fixedFromISO(int weekyear, int weekOfWeekyear, int dayOfWeek) {
139: if (weekyear == 0) {
140: throw new IllegalArgumentException("Illegal weekyear: "
141: + weekyear);
142: }
143: if (weekyear == 1) {
144: weekyear = -1;
145: } else {
146: weekyear--;
147: }
148: return nthWeekday(weekOfWeekyear, 0, weekyear, 12, 28)
149: + dayOfWeek;
150: }
151:
152: /**
153: * @param date days from 0001-01-01
154: * @return iso weekyear, weekOfWeekyear, dayOfWeek (1=Monday to 7)
155: */
156: int[] isoFromFixed(long date) {
157: int weekyear = gjYearFromFixed(date - 3);
158: int nextWeekyear;
159: if (weekyear == -1) {
160: nextWeekyear = 1;
161: } else {
162: nextWeekyear = weekyear + 1;
163: }
164: if (date >= fixedFromISO(nextWeekyear, 1, 1)) {
165: weekyear = nextWeekyear;
166: }
167: int weekOfWeekyear = (int) (div(date
168: - fixedFromISO(weekyear, 1, 1), 7) + 1);
169: int dayOfWeek = (int) amod(date, 7);
170: return new int[] { weekyear, weekOfWeekyear, dayOfWeek };
171: }
172: }
|