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, 30); 035 } 036 037 /** 038 * Constructs with an epoch of 1969-12-19. 039 */ 040 public TestJulianChronology() { 041 super(1969, 12, 19); 042 } 043 044 public TestJulianChronology(int epochYear, int epochMonth, int epochDay) { 045 super(epochYear, epochMonth, epochDay); 046 } 047 048 public DateTimeField dayOfMonth() { 049 return new TestJulianDayOfMonthField(this); 050 } 051 052 public DateTimeField weekyear() { 053 return new TestJulianWeekyearField(this); 054 } 055 056 public DateTimeField monthOfYear() { 057 return new TestJulianMonthOfYearField(this); 058 } 059 060 public DateTimeField year() { 061 return new TestJulianYearField(this); 062 } 063 064 public String toString() { 065 return "TestJulianChronology"; 066 } 067 068 long millisPerYear() { 069 return (long)(365.25 * MILLIS_PER_DAY); 070 } 071 072 long millisPerMonth() { 073 return (long)(365.25 * MILLIS_PER_DAY / 12); 074 } 075 076 boolean isLeapYear(int year) { 077 if (year == 0) { 078 throw new IllegalArgumentException("Illegal year: " + year); 079 } 080 return mod(year, 4) == (year > 0 ? 0 : 3); 081 } 082 083 /** 084 * @return days from 0001-01-01 085 */ 086 long fixedFromGJ(int year, int monthOfYear, int dayOfMonth) { 087 if (year == 0) { 088 throw new IllegalArgumentException("Illegal year: " + year); 089 } 090 int y = (year < 0) ? year + 1 : year; 091 long y_m1 = y - 1; 092 long f = JULIAN_EPOCH - 1 + 365 * y_m1 + div(y_m1, 4) 093 + div(367 * monthOfYear - 362, 12) + dayOfMonth; 094 if (monthOfYear > 2) { 095 f += isLeapYear(year) ? -1 : -2; 096 } 097 return f; 098 } 099 100 /** 101 * @param date days from 0001-01-01 102 * @return gj year 103 */ 104 int gjYearFromFixed(long date) { 105 return gjFromFixed(date)[0]; 106 } 107 108 /** 109 * @param date days from 0001-01-01 110 * @return gj year, monthOfYear, dayOfMonth 111 */ 112 int[] gjFromFixed(long date) { 113 long approx = div(4 * (date - JULIAN_EPOCH) + 1464, 1461); 114 long year = (approx <= 0) ? approx - 1 : approx; 115 int year_i = (int)year; 116 if (year_i != year) { 117 throw new RuntimeException("year cannot be cast to an int: " + year); 118 } 119 long priorDays = date - fixedFromGJ(year_i, 1, 1); 120 long correction; 121 if (date < fixedFromGJ(year_i, 3, 1)) { 122 correction = 0; 123 } else if (isLeapYear(year_i)) { 124 correction = 1; 125 } else { 126 correction = 2; 127 } 128 int monthOfYear = (int)div(12 * (priorDays + correction) + 373, 367); 129 int day = (int)(date - fixedFromGJ(year_i, monthOfYear, 1) + 1); 130 131 return new int[]{year_i, monthOfYear, day}; 132 } 133 134 long fixedFromISO(int weekyear, int weekOfWeekyear, int dayOfWeek) { 135 if (weekyear == 0) { 136 throw new IllegalArgumentException("Illegal weekyear: " + weekyear); 137 } 138 if (weekyear == 1) { 139 weekyear = -1; 140 } else { 141 weekyear--; 142 } 143 return nthWeekday(weekOfWeekyear, 0, weekyear, 12, 28) + dayOfWeek; 144 } 145 146 /** 147 * @param date days from 0001-01-01 148 * @return iso weekyear, weekOfWeekyear, dayOfWeek (1=Monday to 7) 149 */ 150 int[] isoFromFixed(long date) { 151 int weekyear = gjYearFromFixed(date - 3); 152 int nextWeekyear; 153 if (weekyear == -1) { 154 nextWeekyear = 1; 155 } else { 156 nextWeekyear = weekyear + 1; 157 } 158 if (date >= fixedFromISO(nextWeekyear, 1, 1)) { 159 weekyear = nextWeekyear; 160 } 161 int weekOfWeekyear = (int)(div(date - fixedFromISO(weekyear, 1, 1), 7) + 1); 162 int dayOfWeek = (int)amod(date, 7); 163 return new int[]{weekyear, weekOfWeekyear, dayOfWeek}; 164 } 165 }