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