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);
}
}
|