1 /*******************************************************************************
2
3 Copyright:
4 Copyright (c) 2005 John Chapman.
5 Some parts copyright (c) 2009-2016 dunnhumby Germany GmbH.
6 All rights reserved.
7
8 License:
9 Tango Dual License: 3-Clause BSD License / Academic Free License v3.0.
10 See LICENSE_TANGO.txt for details.
11
12 Version:
13 Mid 2005: Initial release
14 Apr 2007: reshaped
15
16 Authors: John Chapman, Kris
17
18 ******************************************************************************/
19
20 module ocean.time.chrono.GregorianBased;
21
22 import ocean.core.ExceptionDefinitions;
23
24 import ocean.time.Time;
25
26 import ocean.time.chrono.Gregorian;
27
28
29
30 class GregorianBased : Gregorian {
31
32 private EraRange[] eraRanges_;
33 private int maxYear_, minYear_;
34 private int currentEra_ = -1;
35
36 this()
37 {
38 eraRanges_ = EraRange.getEraRanges(id);
39 maxYear_ = eraRanges_[0].maxEraYear;
40 minYear_ = eraRanges_[0].minEraYear;
41 }
42
43 public override Time toTime(uint year, uint month, uint day, uint hour, uint minute, uint second, uint millisecond, uint era) {
44 year = getGregorianYear(year, era);
45 return super.toTime(year, month, day, hour, minute, second, millisecond, era);
46 }
47 public override uint getYear(Time time) {
48 auto ticks = time.ticks;
49 auto year = extractPart(time.ticks, DatePart.Year);
50 foreach (EraRange eraRange; eraRanges_) {
51 if (ticks >= eraRange.ticks)
52 return year - eraRange.yearOffset;
53 }
54 throw new IllegalArgumentException("Value was out of range.");
55 }
56
57 public override uint getEra(Time time) {
58 auto ticks = time.ticks;
59 foreach (EraRange eraRange; eraRanges_) {
60 if (ticks >= eraRange.ticks)
61 return eraRange.era;
62 }
63 throw new IllegalArgumentException("Value was out of range.");
64 }
65
66 public override uint[] eras() {
67 uint[] result;
68 foreach (EraRange eraRange; eraRanges_)
69 result ~= eraRange.era;
70 return result;
71 }
72
73 private uint getGregorianYear(uint year, uint era) {
74 if (era == 0)
75 era = currentEra;
76 foreach (EraRange eraRange; eraRanges_) {
77 if (era == eraRange.era) {
78 if (year >= eraRange.minEraYear && year <= eraRange.maxEraYear)
79 return eraRange.yearOffset + year;
80 throw new IllegalArgumentException("Value was out of range.");
81 }
82 }
83 throw new IllegalArgumentException("Era value was not valid.");
84 }
85
86 protected uint currentEra() {
87 if (currentEra_ == -1)
88 currentEra_ = EraRange.getCurrentEra(id);
89 return currentEra_;
90 }
91 }
92
93
94
95 package struct EraRange {
96
97 private static EraRange[][uint] eraRanges;
98 private static uint[uint] currentEras;
99 private static bool initialized_;
100
101 package uint era;
102 package long ticks;
103 package uint yearOffset;
104 package uint minEraYear;
105 package uint maxEraYear;
106
107 private static void initialize() {
108 if (!initialized_) {
109 long getTicks(uint year, uint month, uint day)
110 {
111 return Gregorian.generic.getDateTicks(year, month, day, Gregorian.AD_ERA);
112 }
113 eraRanges[Gregorian.JAPAN] ~= EraRange(4, getTicks(1989, 1, 8), 1988, 1, Gregorian.MAX_YEAR);
114 eraRanges[Gregorian.JAPAN] ~= EraRange(3, getTicks(1926, 12, 25), 1925, 1, 1989);
115 eraRanges[Gregorian.JAPAN] ~= EraRange(2, getTicks(1912, 7, 30), 1911, 1, 1926);
116 eraRanges[Gregorian.JAPAN] ~= EraRange(1, getTicks(1868, 9, 8), 1867, 1, 1912);
117 eraRanges[Gregorian.TAIWAN] ~= EraRange(1, getTicks(1912, 1, 1), 1911, 1, Gregorian.MAX_YEAR);
118 eraRanges[Gregorian.KOREA] ~= EraRange(1, getTicks(1, 1, 1), -2333, 2334, Gregorian.MAX_YEAR);
119 eraRanges[Gregorian.THAI] ~= EraRange(1, getTicks(1, 1, 1), -543, 544, Gregorian.MAX_YEAR);
120 currentEras[Gregorian.JAPAN] = 4;
121 currentEras[Gregorian.TAIWAN] = 1;
122 currentEras[Gregorian.KOREA] = 1;
123 currentEras[Gregorian.THAI] = 1;
124 initialized_ = true;
125 }
126 }
127
128 package static EraRange[] getEraRanges(uint calID) {
129 if (!initialized_)
130 initialize();
131 return eraRanges[calID];
132 }
133
134 package static uint getCurrentEra(uint calID) {
135 if (!initialized_)
136 initialize();
137 return currentEras[calID];
138 }
139
140 private static EraRange opCall(uint era, long ticks, uint yearOffset, uint minEraYear, uint prevEraYear) {
141 EraRange eraRange;
142 eraRange.era = era;
143 eraRange.ticks = ticks;
144 eraRange.yearOffset = yearOffset;
145 eraRange.minEraYear = minEraYear;
146 eraRange.maxEraYear = prevEraYear - yearOffset;
147 return eraRange;
148 }
149
150 }
151