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 /**
019 * A reference Gregorian chronology implementation, intended for testing
020 * purposes only. Correctness is favored over performance. The key functions
021 * for date calculations are based on ones provided in "Calendrical
022 * Calculations", ISBN 0-521-77752-6.
023 *
024 * @author Brian S O'Neill
025 */
026 public final class TestGregorianChronology extends TestGJChronology {
027 /**
028 * Constructs with an epoch of 1970-01-01.
029 */
030 public TestGregorianChronology() {
031 super(1970, 1, 1);
032 }
033
034 public TestGregorianChronology(int epochYear, int epochMonth, int epochDay) {
035 super(epochYear, epochMonth, epochDay);
036 }
037
038 public String toString() {
039 return "TestGregorianChronology";
040 }
041
042 long millisPerYear() {
043 return (long)(365.2425 * MILLIS_PER_DAY);
044 }
045
046 long millisPerMonth() {
047 return (long)(365.2425 * MILLIS_PER_DAY / 12);
048 }
049
050 boolean isLeapYear(int year) {
051 if (mod(year, 4) == 0) {
052 int t = (int)mod(year, 400);
053 if (t != 100 && t != 200 && t != 300) {
054 return true;
055 }
056 }
057 return false;
058 }
059
060 /**
061 * @return days from 0001-01-01
062 */
063 long fixedFromGJ(int year, int monthOfYear, int dayOfMonth) {
064 long year_m1 = year - 1;
065 long f = 365 * year_m1 + div(year_m1, 4) - div(year_m1, 100)
066 + div(year_m1, 400) + div(367 * monthOfYear - 362, 12) + dayOfMonth;
067 if (monthOfYear > 2) {
068 f += isLeapYear(year) ? -1 : -2;
069 }
070 return f;
071 }
072
073 /**
074 * @param date days from 0001-01-01
075 * @return gj year
076 */
077 int gjYearFromFixed(long date) {
078 long d0 = date - 1;
079 long n400 = div(d0, 146097);
080 long d1 = mod(d0, 146097);
081 long n100 = div(d1, 36524);
082 long d2 = mod(d1, 36524);
083 long n4 = div(d2, 1461);
084 long d3 = mod(d2, 1461);
085 long n1 = div(d3, 365);
086 long year = 400 * n400 + 100 * n100 + 4 * n4 + n1;
087 if (!(n100 == 4 || n1 == 4)) {
088 year += 1;
089 }
090
091 int year_i = (int)year;
092 if (year_i == year) {
093 return year_i;
094 } else {
095 throw new RuntimeException("year cannot be cast to an int: " + year);
096 }
097 }
098
099 /**
100 * @param date days from 0001-01-01
101 * @return gj year, monthOfYear, dayOfMonth
102 */
103 int[] gjFromFixed(long date) {
104 int year = gjYearFromFixed(date);
105 long priorDays = date - fixedFromGJ(year, 1, 1);
106 long correction;
107 if (date < fixedFromGJ(year, 3, 1)) {
108 correction = 0;
109 } else if (isLeapYear(year)) {
110 correction = 1;
111 } else {
112 correction = 2;
113 }
114 int monthOfYear = (int)div(12 * (priorDays + correction) + 373, 367);
115 int day = (int)(date - fixedFromGJ(year, monthOfYear, 1) + 1);
116
117 return new int[]{year, monthOfYear, day};
118 }
119
120 long fixedFromISO(int weekyear, int weekOfWeekyear, int dayOfWeek) {
121 return nthWeekday(weekOfWeekyear, 0, weekyear - 1, 12, 28) + dayOfWeek;
122 }
123
124 /**
125 * @param date days from 0001-01-01
126 * @return iso weekyear, weekOfWeekyear, dayOfWeek (1=Monday to 7)
127 */
128 int[] isoFromFixed(long date) {
129 int weekyear = gjYearFromFixed(date - 3);
130 if (date >= fixedFromISO(weekyear + 1, 1, 1)) {
131 weekyear += 1;
132 }
133 int weekOfWeekyear = (int)(div(date - fixedFromISO(weekyear, 1, 1), 7) + 1);
134 int dayOfWeek = (int)amod(date, 7);
135 return new int[]{weekyear, weekOfWeekyear, dayOfWeek};
136 }
137 }