| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145 | /******************************************************************************* copyright: Copyright (c) 2005 John Chapman. All rights reserved license: BSD style: $(LICENSE) version: Mid 2005: Initial release Apr 2007: reshaped author: John Chapman, Kris ******************************************************************************/ module tango.time.chrono.GregorianBased; private import tango.core.Exception; private import tango.time.Time; private import tango.time.chrono.Gregorian; class GregorianBased : Gregorian { private EraRange[] eraRanges_; private int maxYear_, minYear_; private int currentEra_ = -1; this() { eraRanges_ = EraRange.getEraRanges(id); maxYear_ = eraRanges_[0].maxEraYear; minYear_ = eraRanges_[0].minEraYear; currentEra_ = EraRange.getCurrentEra(id); } public override const Time toTime(uint year, uint month, uint day, uint hour, uint minute, uint second, uint millisecond, uint era) { year = getGregorianYear(year, era); return super.toTime(year, month, day, hour, minute, second, millisecond, era); } public override const uint getYear(const(Time) time) { auto ticks = time.ticks; auto year = extractPart(time.ticks, DatePart.Year); foreach (EraRange eraRange; eraRanges_) { if (ticks >= eraRange.ticks) return year - eraRange.yearOffset; } throw new IllegalArgumentException("Value was out of range."); } public override const uint getEra(const(Time) time) { auto ticks = time.ticks; foreach (EraRange eraRange; eraRanges_) { if (ticks >= eraRange.ticks) return eraRange.era; } throw new IllegalArgumentException("Value was out of range."); } public override const uint[] eras() { uint[] result; foreach (EraRange eraRange; eraRanges_) result ~= eraRange.era; return result; } private const uint getGregorianYear(uint year, uint era) { if (era == 0) era = currentEra; foreach (EraRange eraRange; eraRanges_) { if (era == eraRange.era) { if (year >= eraRange.minEraYear && year <= eraRange.maxEraYear) return eraRange.yearOffset + year; throw new IllegalArgumentException("Value was out of range."); } } throw new IllegalArgumentException("Era value was not valid."); } @property protected const uint currentEra() { return currentEra_; } } package struct EraRange { private static EraRange[][uint] eraRanges; private static uint[uint] currentEras; private static bool initialized_; package uint era; package long ticks; package uint yearOffset; package uint minEraYear; package uint maxEraYear; private static void initialize() { if (!initialized_) { long getTicks(uint year, uint month, uint day) { return Gregorian.generic.getDateTicks(year, month, day, Gregorian.AD_ERA); } eraRanges[Gregorian.JAPAN] ~= EraRange(4, getTicks(1989, 1, 8), 1988, 1, Gregorian.MAX_YEAR); eraRanges[Gregorian.JAPAN] ~= EraRange(3, getTicks(1926, 12, 25), 1925, 1, 1989); eraRanges[Gregorian.JAPAN] ~= EraRange(2, getTicks(1912, 7, 30), 1911, 1, 1926); eraRanges[Gregorian.JAPAN] ~= EraRange(1, getTicks(1868, 9, 8), 1867, 1, 1912); eraRanges[Gregorian.TAIWAN] ~= EraRange(1, getTicks(1912, 1, 1), 1911, 1, Gregorian.MAX_YEAR); eraRanges[Gregorian.KOREA] ~= EraRange(1, getTicks(1, 1, 1), -2333, 2334, Gregorian.MAX_YEAR); eraRanges[Gregorian.THAI] ~= EraRange(1, getTicks(1, 1, 1), -543, 544, Gregorian.MAX_YEAR); currentEras[Gregorian.JAPAN] = 4; currentEras[Gregorian.TAIWAN] = 1; currentEras[Gregorian.KOREA] = 1; currentEras[Gregorian.THAI] = 1; initialized_ = true; } } package static EraRange[] getEraRanges(uint calID) { if (!initialized_) initialize(); return eraRanges[calID]; } package static uint getCurrentEra(uint calID) { if (!initialized_) initialize(); return currentEras[calID]; } private static EraRange opCall(uint era, long ticks, uint yearOffset, uint minEraYear, uint prevEraYear) { EraRange eraRange; eraRange.era = era; eraRange.ticks = ticks; eraRange.yearOffset = yearOffset; eraRange.minEraYear = minEraYear; eraRange.maxEraYear = prevEraYear - yearOffset; return eraRange; } } |