| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 | /******************************************************************************* 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, snoyberg ******************************************************************************/ module tango.time.chrono.Hebrew; private import tango.core.Exception; private import tango.time.chrono.Calendar; /** * $(ANCHOR _Hebrew) * Represents the Hebrew calendar. */ public class Hebrew : Calendar { private enum uint[14][7] MonthDays = [ // month // year type [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], [ 0, 30, 29, 29, 29, 30, 29, 0, 30, 29, 30, 29, 30, 29 ], // 1 [ 0, 30, 29, 30, 29, 30, 29, 0, 30, 29, 30, 29, 30, 29 ], // 2 [ 0, 30, 30, 30, 29, 30, 29, 0, 30, 29, 30, 29, 30, 29 ], // 3 [ 0, 30, 29, 29, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29 ], // 4 [ 0, 30, 29, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29 ], // 5 [ 0, 30, 30, 30, 29, 30, 30, 29, 30, 29, 30, 29, 30, 29 ] // 6 ]; private enum uint YearOfOneAD = 3760; private enum uint DaysToOneAD = cast(int)(YearOfOneAD * 365.2735); private enum uint PartsPerHour = 1080; private enum uint PartsPerDay = 24 * PartsPerHour; private enum uint DaysPerMonth = 29; private enum uint DaysPerMonthFraction = 12 * PartsPerHour + 793; private enum uint PartsPerMonth = DaysPerMonth * PartsPerDay + DaysPerMonthFraction; private enum uint FirstNewMoon = 11 * PartsPerHour + 204; private uint minYear_ = YearOfOneAD + 1583; private uint maxYear_ = YearOfOneAD + 2240; /** * Represents the current era. */ public enum uint HEBREW_ERA = 1; /** * Overridden. Returns a Time value set to the specified date and time in the specified _era. * Params: * year = An integer representing the _year. * month = An integer representing the _month. * day = An integer representing the _day. * hour = An integer representing the _hour. * minute = An integer representing the _minute. * second = An integer representing the _second. * millisecond = An integer representing the _millisecond. * era = An integer representing the _era. * Returns: A Time set to the specified date and time. */ public override const Time toTime(uint year, uint month, uint day, uint hour, uint minute, uint second, uint millisecond, uint era) { checkYear(year, era); return getGregorianTime(year, month, day, hour, minute, second, millisecond); } /** * Overridden. Returns the day of the week in the specified Time. * Params: time = A Time value. * Returns: A DayOfWeek value representing the day of the week of time. */ public override const DayOfWeek getDayOfWeek(const(Time) time) { return cast(DayOfWeek) cast(uint) ((time.ticks / TimeSpan.TicksPerDay + 1) % 7); } /** * Overridden. Returns the day of the month in the specified Time. * Params: time = A Time value. * Returns: An integer representing the day of the month of time. */ public override const uint getDayOfMonth(const(Time) time) { auto year = getYear(time); auto yearType = getYearType(year); auto days = getStartOfYear(year) - DaysToOneAD; auto day = cast(int)(time.ticks / TimeSpan.TicksPerDay) - days; uint n; while (n < 12 && day >= MonthDays[yearType][n + 1]) { day -= MonthDays[yearType][n + 1]; n++; } return day + 1; } /** * Overridden. Returns the day of the year in the specified Time. * Params: time = A Time value. * Returns: An integer representing the day of the year of time. */ public override const uint getDayOfYear(const(Time) time) { auto year = getYear(time); auto days = getStartOfYear(year) - DaysToOneAD; return (cast(uint)(time.ticks / TimeSpan.TicksPerDay) - days) + 1; } /** * Overridden. Returns the month in the specified Time. * Params: time = A Time value. * Returns: An integer representing the month in time. */ public override const uint getMonth(const(Time) time) { auto year = getYear(time); auto yearType = getYearType(year); auto days = getStartOfYear(year) - DaysToOneAD; auto day = cast(int)(time.ticks / TimeSpan.TicksPerDay) - days; uint n; while (n < 12 && day >= MonthDays[yearType][n + 1]) { day -= MonthDays[yearType][n + 1]; n++; } return n + 1; } /** * Overridden. Returns the year in the specified Time. * Params: time = A Time value. * Returns: An integer representing the year in time. */ public override const uint getYear(const(Time) time) { auto day = cast(uint)(time.ticks / TimeSpan.TicksPerDay) + DaysToOneAD; uint low = minYear_, high = maxYear_; // Perform a binary search. while (low <= high) { auto mid = low + (high - low) / 2; auto startDay = getStartOfYear(mid); if (day < startDay) high = mid - 1; else if (day >= startDay && day < getStartOfYear(mid + 1)) return mid; else low = mid + 1; } return low; } /** * Overridden. Returns the era in the specified Time. * Params: time = A Time value. * Returns: An integer representing the ear in time. */ public override const uint getEra(const(Time) time) { return HEBREW_ERA; } /** * Overridden. Returns the number of days in the specified _year and _month of the specified _era. * Params: * year = An integer representing the _year. * month = An integer representing the _month. * era = An integer representing the _era. * Returns: The number of days in the specified _year and _month of the specified _era. */ public override const uint getDaysInMonth(uint year, uint month, uint era) { checkYear(year, era); return MonthDays[getYearType(year)][month]; } /** * Overridden. Returns the number of days in the specified _year of the specified _era. * Params: * year = An integer representing the _year. * era = An integer representing the _era. * Returns: The number of days in the specified _year in the specified _era. */ public override const uint getDaysInYear(uint year, uint era) { return getStartOfYear(year + 1) - getStartOfYear(year); } /** * Overridden. Returns the number of months in the specified _year of the specified _era. * Params: * year = An integer representing the _year. * era = An integer representing the _era. * Returns: The number of months in the specified _year in the specified _era. */ public override const uint getMonthsInYear(uint year, uint era) { return isLeapYear(year, era) ? 13 : 12; } /** * Overridden. Indicates whether the specified _year in the specified _era is a leap _year. * Params: year = An integer representing the _year. * Params: era = An integer representing the _era. * Returns: true is the specified _year is a leap _year; otherwise, false. */ public override const bool isLeapYear(uint year, uint era) { checkYear(year, era); // true if year % 19 == 0, 3, 6, 8, 11, 14, 17 return ((7 * year + 1) % 19) < 7; } /** * $(I Property.) Overridden. Retrieves the list of eras in the current calendar. * Returns: An integer array representing the eras in the current calendar. */ public override const uint[] eras() { auto tmp = [HEBREW_ERA]; return tmp.dup; } /** * $(I Property.) Overridden. Retrieves the identifier associated with the current calendar. * Returns: An integer representing the identifier of the current calendar. */ public override const uint id() { return HEBREW; } private const void checkYear(uint year, uint era) { if ((era != CURRENT_ERA && era != HEBREW_ERA) || (year > maxYear_ || year < minYear_)) throw new IllegalArgumentException("Value was out of range."); } private const uint getYearType(uint year) { int yearLength = getStartOfYear(year + 1) - getStartOfYear(year); if (yearLength > 380) yearLength -= 30; switch (yearLength) { case 353: // "deficient" return 1; case 383: // "deficient" leap return 4; case 354: // "normal" return 2; case 384: // "normal" leap return 5; case 355: // "complete" return 3; case 385: // "complete" leap return 6; default: break; } // Satisfies -w throw new IllegalArgumentException("Value was not valid."); } private const uint getStartOfYear(uint year) { auto months = (235 * year - 234) / 19; auto fraction = months * DaysPerMonthFraction + FirstNewMoon; auto day = months * 29 + (fraction / PartsPerDay); fraction %= PartsPerDay; auto dayOfWeek = day % 7; if (dayOfWeek == 2 || dayOfWeek == 4 || dayOfWeek == 6) { day++; dayOfWeek = day % 7; } if (dayOfWeek == 1 && fraction > 15 * PartsPerHour + 204 && !isLeapYear(year, CURRENT_ERA)) day += 2; else if (dayOfWeek == 0 && fraction > 21 * PartsPerHour + 589 && isLeapYear(year, CURRENT_ERA)) day++; return day; } private const Time getGregorianTime(uint year, uint month, uint day, uint hour, uint minute, uint second, uint millisecond) { auto yearType = getYearType(year); auto days = getStartOfYear(year) - DaysToOneAD + day - 1; for (int i = 1; i <= month; i++) days += MonthDays[yearType][i - 1]; return Time((days * TimeSpan.TicksPerDay) + getTimeTicks(hour, minute, second)) + TimeSpan.fromMillis(millisecond); } } |