| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 | /******************************************************************************* 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.Hijri; private import tango.time.chrono.Calendar; /** * $(ANCHOR _Hijri) * Represents the Hijri calendar. */ public class Hijri : Calendar { private enum uint[] DAYS_TO_MONTH = [ 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 ]; /** * Represents the current era. */ public enum uint HIJRI_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) { return Time((daysSinceJan1(year, month, day) - 1) * TimeSpan.TicksPerDay + getTimeTicks(hour, minute, second)) + TimeSpan.fromMillis(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) { return extractPart(time.ticks, DatePart.Day); } /** * 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) { return extractPart(time.ticks, DatePart.DayOfYear); } /** * 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 getMonth(const(Time) time) { return extractPart(time.ticks, DatePart.Month); } /** * 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) { return extractPart(time.ticks, DatePart.Year); } /** * 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 HIJRI_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) { if (month == 12) return isLeapYear(year, CURRENT_ERA) ? 30 : 29; return (month % 2 == 1) ? 30 : 29; } /** * 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 isLeapYear(year, era) ? 355 : 354; } /** * 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 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) { return (14 + 11 * year) % 30 < 11; } /** * $(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 = [HIJRI_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 HIJRI; } private const long daysToYear(uint year) { int cycle = ((year - 1) / 30) * 30; int remaining = year - cycle - 1; long days = ((cycle * 10631L) / 30L) + 227013L; while (remaining > 0) { days += 354 + (isLeapYear(remaining, CURRENT_ERA) ? 1 : 0); remaining--; } return days; } private const long daysSinceJan1(uint year, uint month, uint day) { return cast(long)(daysToYear(year) + DAYS_TO_MONTH[month - 1] + day); } private const int extractPart(long ticks, DatePart part) { long days = TimeSpan(ticks).days + 1; int year = cast(int)(((days - 227013) * 30) / 10631) + 1; long daysUpToYear = daysToYear(year); long daysInYear = getDaysInYear(year, CURRENT_ERA); if (days < daysUpToYear) { daysUpToYear -= daysInYear; year--; } else if (days == daysUpToYear) { year--; daysUpToYear -= getDaysInYear(year, CURRENT_ERA); } else if (days > daysUpToYear + daysInYear) { daysUpToYear += daysInYear; year++; } if (part == DatePart.Year) return year; days -= daysUpToYear; if (part == DatePart.DayOfYear) return cast(int)days; int month = 1; while (month <= 12 && days > DAYS_TO_MONTH[month - 1]) month++; month--; if (part == DatePart.Month) return month; return cast(int)(days - DAYS_TO_MONTH[month - 1]); } } |