CalendricalCalculations.cs 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120
  1. // CalendricalCalculations.cs
  2. //
  3. // (C) Ulrich Kunitz 2002
  4. //
  5. namespace System.Globalization {
  6. using System.Collections;
  7. /// <summary>A class that provides mathematical functions.</summary>
  8. /// <remarks>
  9. /// <para>
  10. /// We are breaking the .Net
  11. /// naming conventions to be compatible to the "Calendrical Calculations"
  12. /// bool.
  13. /// </para>
  14. /// </remarks>
  15. internal class CCMath {
  16. /// <summary>
  17. /// A static method which rounds a double value.
  18. /// </summary>
  19. /// <param name="x">The double value to round.</param>
  20. /// <returns>The rounded double.</returns>
  21. public static double round(double x) {
  22. return System.Math.Floor(x+0.5);
  23. }
  24. /// <summary>
  25. /// A static method that computes the remainder of the division
  26. /// of two doubles.
  27. /// </summary>
  28. /// <param name="x">The double value which is divided.</param>
  29. /// <param name="y">The divisor.</param>
  30. /// <returns>The remainder as double value.</returns>
  31. public static double mod(double x, double y) {
  32. return x - y * System.Math.Floor(x/y);
  33. }
  34. /// <summary>
  35. /// The static method divides two integers.
  36. /// </summary>
  37. /// <param name="x">The integer x value.</param>
  38. /// <param name="y">The integer y value.</param>
  39. /// <returns>The qotient of x and y defined by floor(x/y).
  40. /// </returns>
  41. /// <remarks>
  42. /// Please notify that the function is not compatible to the standard
  43. /// integer divide operation /.
  44. /// </remarks>
  45. public static int div(int x, int y) {
  46. return (int)System.Math.Floor((double)x/(double)y);
  47. }
  48. /// <summary>
  49. /// The static method computes the remainder of two integers.
  50. /// </summary>
  51. /// <param name="x">The integer value which will be divided.</param>
  52. /// <param name="y">The divisor integer value.</param>
  53. /// <returns> The remainder as integer value.</returns>
  54. /// <remarks>
  55. /// Please notify that the method is not compatible to the C#
  56. /// remainder operation %.
  57. /// </remarks>
  58. public static int mod(int x, int y) {
  59. return x - y * div(x, y);
  60. }
  61. /// <summary>
  62. /// A static method that combines integer division and remainder
  63. /// computation.
  64. /// </summary>
  65. /// <param name="remainder">Remainder integer output value.
  66. /// </param>
  67. /// <param name="x">Integer to be divided.</param>
  68. /// <param name="y">Divisor integer value.</param>
  69. /// <returns>The quotient as integer.</returns>
  70. /// <seealso cref="M:div"/>
  71. /// <seealso cref="M:mod"/>
  72. public static int div_mod(out int remainder, int x, int y) {
  73. int d = div(x, y);
  74. remainder = x - y * d;
  75. return d;
  76. }
  77. /// <summary>
  78. /// A static method returning the sign of the argument.
  79. /// </summary>
  80. /// <param name="x">The double argument.</param>
  81. /// <returns>An integer value: -1 for a negative argument;
  82. /// 0 for a zero argument, and 1 for a positive argument.
  83. /// </returns>
  84. public static int signum(double x) {
  85. if (x < 0.0)
  86. return -1;
  87. if (x == 0.0)
  88. return 0;
  89. return 1;
  90. }
  91. /// <summary>
  92. /// A static method returning the sign of the integer
  93. /// argument.
  94. /// </summary>
  95. /// <param name="x">The integer argument.</param>
  96. /// <returns>An integer value: -1 for a negative argument;
  97. /// 0 for a zero argument, and 1 for a positive argument.
  98. /// </returns>
  99. public static int signum(int x) {
  100. if (x < 0)
  101. return -1;
  102. if (x == 0)
  103. return 0;
  104. return 1;
  105. }
  106. /// <summary>
  107. /// An adjusted remainder function as defined in "Calendrical
  108. /// Calculations".
  109. /// </summary>
  110. /// <param name="x">The double x argument.</param>
  111. /// <param name="y">The double y argument, the divisor.</param>
  112. /// <returns>A double value representing remainder; but instead 0.0
  113. /// the divisor y is returned.
  114. /// </returns>
  115. public static double amod(double x, double y) {
  116. double d = mod(x, y);
  117. return (d == 0.0) ? y : d;
  118. }
  119. /// <summary>
  120. /// The adjusted remainder functions for integers as defined in
  121. /// "Calendrical Calculations".
  122. /// </summary>
  123. /// <param name="x">The integer argument to be divided.</param>
  124. /// <param name="y">The integer divisor argument.</param>
  125. /// <returns>The remainder as an integer; however instead 0
  126. /// is the divisor y returned.
  127. /// </returns>
  128. public static int amod(int x, int y) {
  129. int i = mod(x, y);
  130. return (i == 0) ? y : i;
  131. }
  132. }
  133. /// <summary>The class implements methods to handle the fixed date value from
  134. /// the "Calendrical Calculations" books.
  135. /// </summary>
  136. /// <remarks>
  137. /// <para>
  138. /// For implementing the Calendar classes I used the algorithms from the
  139. /// book "Calendrical Calculations" by Nachum Dershowitz and Edward M.
  140. /// Rheingold, second reprint 1998. Trying to prevent the introduction of new
  141. /// bugs, I implemented their algorithms in the
  142. /// <see cref="N:CalendricalCalculations"/>
  143. /// namespace and wrapped it in the calendar classes.
  144. /// </para>
  145. /// <para>
  146. /// The fixed day number is also known as R.D. - rata die.
  147. /// Midnight at the onset of Monday,
  148. /// January 1, year 1 (Gregorian) is R.D. 1.
  149. /// </para>
  150. /// <para>Here are all my references:</para>
  151. /// <list type="table">
  152. /// <item><description>
  153. /// [1] Nachum Dershowitz and Edward M. Rheingold: "Calendrical Calculations";
  154. /// Cambridge University Press; second reprint 1998.
  155. /// </description></item>
  156. /// <item><description>
  157. /// [2] P. Kenneth Seidelmann (ed.): "Explanatory Supplement to the Astronomical
  158. /// Almanac"; University Science Books, Sausalito; 1992
  159. /// </description></item>
  160. /// <item><description>
  161. /// [3] F. Richard Stephenson: "Historical Eclipses and Earth Rotation";
  162. /// Cambridge University Press; 1997
  163. /// </description></item>
  164. /// </list>
  165. /// </remarks>
  166. internal class CCFixed {
  167. /// <summary>The method computes the
  168. /// <see cref="T:System.DateTime"/>
  169. /// from a fixed day number.
  170. /// </summary>
  171. /// <param name="date">A integer representing the fixed day number.
  172. /// </param>
  173. /// <returns>The <see cref="T:System.DateTime"/> representing
  174. /// the date.
  175. /// </returns>
  176. public static System.DateTime ToDateTime(int date) {
  177. long ticks = (date - 1) * System.TimeSpan.TicksPerDay;
  178. return new System.DateTime(ticks);
  179. }
  180. /// <summary>The method computes the
  181. /// <see cref="T:System.DateTime"/>
  182. /// from a fixed day number and time arguments.
  183. /// </summary>
  184. /// <param name="date">An integer representing the fixed day number.
  185. /// </param>
  186. /// <param name="hour">An integer argument specifying the hour.
  187. /// </param>
  188. /// <param name="minute">An integer argument specifying the minute.
  189. /// </param>
  190. /// <param name="second">An integer argument giving the second.
  191. /// </param>
  192. /// <param name="milliseconds">An double argument specifying
  193. /// the milliseconds. Notice that
  194. /// <see cref="T:System.DateTime"/> has 100 nanosecond resolution.
  195. /// </param>
  196. /// <returns>The <see cref="T:System.DateTime"/> representing
  197. /// the date.
  198. /// </returns>
  199. public static System.DateTime ToDateTime(int date,
  200. int hour, int minute, int second, double milliseconds)
  201. {
  202. System.DateTime time = ToDateTime(date);
  203. time = time.AddHours(hour);
  204. time = time.AddMinutes(minute);
  205. time = time.AddSeconds(second);
  206. return time.AddMilliseconds(milliseconds);
  207. }
  208. /// <summary>
  209. /// A static method computing the fixed day number from a
  210. /// <see cref="T:System.DateTime"/> value.
  211. /// </summary>
  212. /// <param name="time">A
  213. /// <see cref="T:System.DateTime"/> value representing the date.
  214. /// </param>
  215. /// <returns>The fixed day number as integer representing the date.
  216. /// </returns>
  217. public static int FromDateTime(System.DateTime time) {
  218. return 1 + (int)(time.Ticks / System.TimeSpan.TicksPerDay);
  219. }
  220. /// <summary>
  221. /// The static method computes the <see cref="T:DayOfWeek"/>.
  222. /// </summary>
  223. /// <param name="date">An integer representing the fixed day number.
  224. /// </param>
  225. /// <returns>The day of week.</returns>
  226. public static DayOfWeek day_of_week(int date) {
  227. return (DayOfWeek)CCMath.mod(date, 7);
  228. }
  229. /// <summary>
  230. /// The static method computes the date of a day of week on or before
  231. /// a particular date.
  232. /// </summary>
  233. /// <param name="date">An integer representing the date as
  234. /// fixed day number.
  235. /// </param>
  236. /// <param name="k">An integer representing the day of the week,
  237. /// starting with 0 for sunday.
  238. /// </param>
  239. /// <returns>The fixed day number of the day of week specified by k
  240. /// on or before the given date.
  241. /// </returns>
  242. public static int kday_on_or_before(int date, int k) {
  243. return date - (int)day_of_week(date-k);
  244. }
  245. /// <summary>
  246. /// The static method computes the date of a day of week on or after
  247. /// a particular date.
  248. /// </summary>
  249. /// <param name="date">An integer representing the date as
  250. /// fixed day number.
  251. /// </param>
  252. /// <param name="k">An integer representing the day of the week,
  253. /// starting with 0 for sunday.
  254. /// </param>
  255. /// <returns>The fixed day number of the day of week specified by k
  256. /// on or after the given date.
  257. /// </returns>
  258. public static int kday_on_or_after(int date, int k) {
  259. return kday_on_or_before(date+6, k);
  260. }
  261. /// <summary>
  262. /// The static method computes the date of a day of week that is
  263. /// nearest to a particular date.
  264. /// </summary>
  265. /// <param name="date">An integer representing the date as
  266. /// fixed day number.
  267. /// </param>
  268. /// <param name="k">An integer representing the day of the week,
  269. /// starting with 0 for sunday.
  270. /// </param>
  271. /// <returns>The fixed day number of the day of week neares to the
  272. /// given date.
  273. /// </returns>
  274. public static int kd_nearest(int date, int k) {
  275. return kday_on_or_before(date+3, k);
  276. }
  277. /// <summary>
  278. /// The static method computes the date of a day of week after
  279. /// a particular date.
  280. /// </summary>
  281. /// <param name="date">An integer representing the date as
  282. /// fixed day number.
  283. /// </param>
  284. /// <param name="k">An integer representing the day of the week,
  285. /// starting with 0 for sunday.
  286. /// </param>
  287. /// <returns>The fixed day number of the day of week specified by k
  288. /// after the given date.
  289. /// </returns>
  290. public static int kday_after(int date, int k) {
  291. return kday_on_or_before(date+7, k);
  292. }
  293. /// <summary>
  294. /// The static method computes the date of a day of week before
  295. /// a particular date.
  296. /// </summary>
  297. /// <param name="date">An integer representing the date as
  298. /// fixed day number.
  299. /// </param>
  300. /// <param name="k">An integer representing the day of the week,
  301. /// starting with 0 for sunday.
  302. /// </param>
  303. /// <returns>The fixed day number of the day of week specified by k
  304. /// before the given date.
  305. /// </returns>
  306. public static int kday_before(int date, int k) {
  307. return kday_on_or_before(date-1, k);
  308. }
  309. } // class CCFixed
  310. /// <summary>
  311. /// A class encapsulating the functions of the Gregorian calendar as static
  312. /// methods.
  313. /// </summary>
  314. /// <remarks>
  315. /// <para>
  316. /// This class is not compatible to
  317. /// <see cref="T:System.Globalization.GregorianCalendar"/>.
  318. /// </para>
  319. /// <para>
  320. /// The fixed day number is also known as R.D. - rata die.
  321. /// Midnight at the onset of Monday,
  322. /// January 1, year 1 (Gregorian) is R.D. 1.
  323. /// </para>
  324. /// <seealso cref="T:CCFixed"/>
  325. /// </remarks>
  326. internal class CCGregorianCalendar {
  327. /// <summary>An integer defining the epoch of the Gregorian calendar
  328. /// as fixed day number.</summary>
  329. /// <remarks>The epoch is January 3, 1 C.E. (Julian).</remarks>
  330. const int epoch = 1;
  331. /// <summary>The enumeration defines the months of the Gregorian
  332. /// calendar.
  333. /// </summary>
  334. public enum Month {
  335. /// <summary>
  336. /// January.
  337. /// </summary>
  338. january = 1,
  339. /// <summary>
  340. /// February.
  341. /// </summary>
  342. february,
  343. /// <summary>
  344. /// March.
  345. /// </summary>
  346. march,
  347. /// <summary>
  348. /// April.
  349. /// </summary>
  350. april,
  351. /// <summary>
  352. /// May.
  353. /// </summary>
  354. may,
  355. /// <summary>
  356. /// June.
  357. /// </summary>
  358. june,
  359. /// <summary>
  360. /// July.
  361. /// </summary>
  362. july,
  363. /// <summary>
  364. /// August.
  365. /// </summary>
  366. august,
  367. /// <summary>
  368. /// September.
  369. /// </summary>
  370. september,
  371. /// <summary>
  372. /// October.
  373. /// </summary>
  374. october,
  375. /// <summary>
  376. /// November.
  377. /// </summary>
  378. november,
  379. /// <summary>
  380. /// December.
  381. /// </summary>
  382. december
  383. };
  384. /// <summary>
  385. /// The method tells whether the year is a leap year.
  386. /// </summary>
  387. /// <param name="year">An integer representing the Gregorian year.
  388. /// </param>
  389. /// <returns>A boolean which is true if <paramref name="year"/> is
  390. /// a leap year.
  391. /// </returns>
  392. public static bool is_leap_year(int year) {
  393. if (CCMath.mod(year, 4) != 0)
  394. return false;
  395. switch (CCMath.mod(year, 400)) {
  396. case 100:
  397. return false;
  398. case 200:
  399. return false;
  400. case 300:
  401. return false;
  402. }
  403. return true;
  404. }
  405. /// <summary>
  406. /// The method returns the fixed day number of the given Gregorian
  407. /// date.
  408. /// </summary>
  409. /// <param name="day">An integer representing the day of the month,
  410. /// counting from 1.
  411. /// </param>
  412. /// <param name="month">An integer representing the month in the
  413. /// Gregorian year.
  414. /// </param>
  415. /// <param name="year">An integer representing the Gregorian year.
  416. /// Non-positive values are allowed also.
  417. /// </param>
  418. /// <returns>An integer value representing the fixed day number.
  419. /// </returns>
  420. public static int fixed_from_dmy(int day, int month, int year) {
  421. int k = epoch - 1;
  422. k += 365 * (year-1);
  423. k += CCMath.div(year-1, 4);
  424. k -= CCMath.div(year-1, 100);
  425. k += CCMath.div(year-1, 400);
  426. k += CCMath.div(367*month-362, 12);
  427. if (month > 2) {
  428. k += is_leap_year(year) ? -1 : -2;
  429. }
  430. k += day;
  431. return k;
  432. }
  433. /// <summary>
  434. /// The method computes the Gregorian year from a fixed day number.
  435. /// </summary>
  436. /// <param name="date">The fixed day number.
  437. /// </param>
  438. /// <returns>An integer value giving the Gregorian year of the date.
  439. /// </returns>
  440. public static int year_from_fixed(int date) {
  441. int d = date - epoch;
  442. int n_400 = CCMath.div_mod(out d, d, 146097);
  443. int n_100 = CCMath.div_mod(out d, d, 36524);
  444. int n_4 = CCMath.div_mod(out d, d, 1461);
  445. int n_1 = CCMath.div(d, 365);
  446. int year = 400*n_400 + 100*n_100 + 4*n_4 + n_1;
  447. return (n_100 == 4 || n_1 == 4) ? year : year + 1;
  448. }
  449. /// <summary>
  450. /// The method computes the Gregorian year and month from a fixed day
  451. /// number.
  452. /// </summary>
  453. /// <param name="month">The output value giving the Gregorian month.
  454. /// </param>
  455. /// <param name="year">The output value giving the Gregorian year.
  456. /// </param>
  457. /// <param name="date">An integer value specifying the fixed day
  458. /// number.</param>
  459. public static void my_from_fixed(out int month, out int year,
  460. int date)
  461. {
  462. year = year_from_fixed(date);
  463. int prior_days = date - fixed_from_dmy(1, (int)Month.january,
  464. year);
  465. int correction;
  466. if (date < fixed_from_dmy(1, (int)Month.march, year)) {
  467. correction = 0;
  468. } else if (is_leap_year(year)) {
  469. correction = 1;
  470. } else {
  471. correction = 2;
  472. }
  473. month = CCMath.div(12 * (prior_days + correction) + 373, 367);
  474. }
  475. /// <summary>
  476. /// The method computes the Gregorian year, month, and day from a
  477. /// fixed day number.
  478. /// </summary>
  479. /// <param name="day">The output value returning the day of the
  480. /// month.
  481. /// </param>
  482. /// <param name="month">The output value giving the Gregorian month.
  483. /// </param>
  484. /// <param name="year">The output value giving the Gregorian year.
  485. /// </param>
  486. /// <param name="date">An integer value specifying the fixed day
  487. /// number.</param>
  488. public static void dmy_from_fixed(out int day, out int month,
  489. out int year,
  490. int date)
  491. {
  492. my_from_fixed(out month, out year, date);
  493. day = date - fixed_from_dmy(1, month, year) + 1;
  494. }
  495. /// <summary>A method computing the Gregorian month from a fixed
  496. /// day number.
  497. /// </summary>
  498. /// <param name="date">An integer specifying the fixed day number.
  499. /// </param>
  500. /// <returns>An integer value representing the Gregorian month.
  501. /// </returns>
  502. public static int month_from_fixed(int date) {
  503. int month, year;
  504. my_from_fixed(out month, out year, date);
  505. return month;
  506. }
  507. /// <summary>
  508. /// A method computing the day of the month from a fixed day number.
  509. /// </summary>
  510. /// <param name="date">An integer specifying the fixed day number.
  511. /// </param>
  512. /// <returns>An integer value representing the day of the month.
  513. /// </returns>
  514. public static int day_from_fixed(int date) {
  515. int day, month, year;
  516. dmy_from_fixed(out day, out month, out year, date);
  517. return day;
  518. }
  519. /// <summary>
  520. /// The method computes the difference between two Gregorian dates.
  521. /// </summary>
  522. /// <param name="dayA">The integer parameter gives the day of month
  523. /// of the first date.
  524. /// </param>
  525. /// <param name="monthA">The integer parameter gives the Gregorian
  526. /// month of the first date.
  527. /// </param>
  528. /// <param name="yearA">The integer parameter gives the Gregorian
  529. /// year of the first date.
  530. /// </param>
  531. /// <param name="dayB">The integer parameter gives the day of month
  532. /// of the second date.
  533. /// </param>
  534. /// <param name="monthB">The integer parameter gives the Gregorian
  535. /// month of the second date.
  536. /// </param>
  537. /// <param name="yearB">The integer parameter gives the Gregorian
  538. /// year of the second date.
  539. /// </param>
  540. /// <returns>An integer giving the difference of days from the first
  541. /// the second date.
  542. /// </returns>
  543. public static int date_difference(int dayA, int monthA, int yearA,
  544. int dayB, int monthB, int yearB)
  545. {
  546. return fixed_from_dmy(dayB, monthB, yearB) -
  547. fixed_from_dmy(dayA, monthA, yearA);
  548. }
  549. /// <summary>
  550. /// The method computes the number of the day in the year from
  551. /// a Gregorian date.
  552. /// </summary>
  553. /// <param name="day">An integer representing the day of the month,
  554. /// counting from 1.
  555. /// </param>
  556. /// <param name="month">An integer representing the month in the
  557. /// Gregorian year.
  558. /// </param>
  559. /// <param name="year">An integer representing the Gregorian year.
  560. /// Non-positive values are allowed also.
  561. /// </param>
  562. /// <returns>An integer value giving the number of the day in the
  563. /// Gregorian year, counting from 1.
  564. /// </returns>
  565. public static int day_number(int day, int month, int year) {
  566. return date_difference(31, (int)Month.december, year-1,
  567. day, month, year);
  568. }
  569. /// <summary>
  570. /// The method computes the days remaining in the given Gregorian
  571. /// year from a Gregorian date.
  572. /// </summary>
  573. /// <param name="day">An integer representing the day of the month,
  574. /// counting from 1.
  575. /// </param>
  576. /// <param name="month">An integer representing the month in the
  577. /// Gregorian year.
  578. /// </param>
  579. /// <param name="year">An integer representing the Gregorian year.
  580. /// Non-positive values are allowed also.
  581. /// </param>
  582. /// <returns>An integer value giving the number of days remaining in
  583. /// the Gregorian year.
  584. /// </returns>
  585. public static int days_remaining(int day, int month, int year) {
  586. return date_difference(day, month, year,
  587. 31, (int)Month.december, year);
  588. }
  589. // Helper functions for the Gregorian calendars.
  590. /// <summary>
  591. /// Adds months to the given date.
  592. /// </summary>
  593. /// <param name="time">The
  594. /// <see cref="T:System.DateTime"/> to which to add
  595. /// months.
  596. /// </param>
  597. /// <param name="months">The number of months to add.</param>
  598. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  599. /// results from adding <paramref name="months"/> to the specified
  600. /// DateTime.</returns>
  601. public static System.DateTime AddMonths(System.DateTime time,
  602. int months)
  603. {
  604. int rd = CCFixed.FromDateTime(time);
  605. int day, month, year;
  606. dmy_from_fixed(out day, out month, out year, rd);
  607. month += months;
  608. rd = fixed_from_dmy(day, month, year);
  609. System.DateTime t = CCFixed.ToDateTime(rd);
  610. return t.Add(time.TimeOfDay);
  611. }
  612. /// <summary>
  613. /// Adds years to the given date.
  614. /// </summary>
  615. /// <param name="time">The
  616. /// <see cref="T:System.DateTime"/> to which to add
  617. /// months.
  618. /// </param>
  619. /// <param name="years">The number of years to add.</param>
  620. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  621. /// results from adding <paramref name="years"/> to the specified
  622. /// DateTime.</returns>
  623. public static System.DateTime AddYears(System.DateTime time,
  624. int years)
  625. {
  626. int rd = CCFixed.FromDateTime(time);
  627. int day, month, year;
  628. dmy_from_fixed(out day, out month, out year, rd);
  629. year += years;
  630. rd = fixed_from_dmy(day, month, year);
  631. System.DateTime t = CCFixed.ToDateTime(rd);
  632. return t.Add(time.TimeOfDay);
  633. }
  634. /// <summary>
  635. /// Gets the of the month from <paramref name="time"/>.
  636. /// </summary>
  637. /// <param name="time">The
  638. /// <see cref="T:System.DateTime"/> that specifies a
  639. /// date.
  640. /// </param>
  641. /// <returns>An integer giving the day of months, starting with 1.
  642. /// </returns>
  643. public static int GetDayOfMonth(System.DateTime time) {
  644. return day_from_fixed(CCFixed.FromDateTime(time));
  645. }
  646. /// <summary>
  647. /// The method gives the number of the day in the year.
  648. /// </summary>
  649. /// <param name="time">The
  650. /// <see cref="T:System.DateTime"/> that specifies a
  651. /// date.
  652. /// </param>
  653. /// <returns>An integer representing the day of the year,
  654. /// starting with 1.</returns>
  655. public static int GetDayOfYear(System.DateTime time) {
  656. int rd = CCFixed.FromDateTime(time);
  657. int year = year_from_fixed(rd);
  658. int rd1_1 = fixed_from_dmy(1, 1, year);
  659. return rd - rd1_1 + 1;
  660. }
  661. /// <summary>
  662. /// A method that gives the number of days of the specified
  663. /// month of the <paramref name="year"/>.
  664. /// </summary>
  665. /// <param name="year">An integer that gives the year in the current
  666. /// era.</param>
  667. /// <param name="month">An integer that gives the month, starting
  668. /// with 1.</param>
  669. /// <returns>An integer that gives the number of days of the
  670. /// specified month.</returns>
  671. public static int GetDaysInMonth(int year, int month) {
  672. int rd1 = fixed_from_dmy(1, month, year);
  673. int rd2 = fixed_from_dmy(1, month+1, year);
  674. return rd2 - rd1;
  675. }
  676. /// <summary>
  677. /// The method gives the number of days in the specified year.
  678. /// </summary>
  679. /// <param name="year">An integer that gives the year.
  680. /// </param>
  681. /// <returns>An integer that gives the number of days of the
  682. /// specified year.</returns>
  683. public static int GetDaysInYear(int year) {
  684. int rd1 = fixed_from_dmy(1, 1, year);
  685. int rd2 = fixed_from_dmy(1, 1, year+1);
  686. return rd2 - rd1;
  687. }
  688. /// <summary>
  689. /// The method gives the number of the month of the specified
  690. /// date.
  691. /// </summary>
  692. /// <param name="time">The
  693. /// <see cref="T:System.DateTime"/> that specifies a
  694. /// date.
  695. /// </param>
  696. /// <returns>An integer representing the month,
  697. /// starting with 1.</returns>
  698. public static int GetMonth(System.DateTime time) {
  699. return month_from_fixed(CCFixed.FromDateTime(time));
  700. }
  701. /// <summary>
  702. /// The method gives the number of the year of the specified
  703. /// date.
  704. /// </summary>
  705. /// <param name="time">The
  706. /// <see cref="T:System.DateTime"/> that specifies a
  707. /// date.
  708. /// </param>
  709. /// <returns>An integer representing the year.
  710. /// </returns>
  711. public static int GetYear(System.DateTime time) {
  712. return year_from_fixed(CCFixed.FromDateTime(time));
  713. }
  714. /// <summary>
  715. /// A virtual method that tells whether the given day
  716. /// is a leap day.
  717. /// </summary>
  718. /// <param name="year">An integer that specifies the year.
  719. /// </param>
  720. /// <param name="month">An integer that specifies the month.
  721. /// </param>
  722. /// <param name="day">An integer that specifies the day.
  723. /// </param>
  724. /// <returns>A boolean that tells whether the given day is a leap
  725. /// day.
  726. /// </returns>
  727. public static bool IsLeapDay(int year, int month, int day) {
  728. return is_leap_year(year) && month == 2 && day == 29;
  729. }
  730. /// <summary>
  731. /// A method that creates the
  732. /// <see cref="T:System.DateTime"/> from the parameters.
  733. /// </summary>
  734. /// <param name="year">An integer that gives the year
  735. /// </param>
  736. /// <param name="month">An integer that specifies the month.
  737. /// </param>
  738. /// <param name="day">An integer that specifies the day.
  739. /// </param>
  740. /// <param name="hour">An integer that specifies the hour.
  741. /// </param>
  742. /// <param name="minute">An integer that specifies the minute.
  743. /// </param>
  744. /// <param name="second">An integer that gives the second.
  745. /// </param>
  746. /// <param name="milliseconds">An integer that gives the
  747. /// milliseconds.
  748. /// </param>
  749. /// <returns>A
  750. /// <see cref="T:system.DateTime"/> representig the date and time.
  751. /// </returns>
  752. public static System.DateTime ToDateTime(int year, int month, int day,
  753. int hour, int minute, int second, int milliseconds)
  754. {
  755. return CCFixed.ToDateTime(fixed_from_dmy(day, month, year),
  756. hour, minute, second, milliseconds);
  757. }
  758. } // class CCGregorianCalendar
  759. /// <summary>
  760. /// A class encapsulating the functions of the Julian calendar as static
  761. /// methods.
  762. /// </summary>
  763. /// <remarks>
  764. /// <para>The algorithms don't support a year 0. Years before Common Era
  765. /// (B.C.E. or B.C.) are negative and years of Common Era (C.E. or A.D.)
  766. /// are positive.
  767. /// </para>
  768. /// <para>
  769. /// This class is not compatible to
  770. /// <see cref="T:System.Globalization.JulianCalendar"/>.
  771. /// </para>
  772. /// <seealso cref="T:CCFixed"/>
  773. /// </remarks>
  774. internal class CCJulianCalendar {
  775. /// <summary>An integer defining the epoch of the Julian calendar
  776. /// as fixed day number.</summary>
  777. /// <remarks>The epoch is December 30, 0 (Gregorian).</remarks>
  778. const int epoch = -1; // 30. 12. 0 Gregorian
  779. /// <summary>The enumeration defines the months of the Julian
  780. /// calendar.
  781. /// </summary>
  782. public enum Month {
  783. /// <summary>
  784. /// January.
  785. /// </summary>
  786. january = 1,
  787. /// <summary>
  788. /// February.
  789. /// </summary>
  790. february,
  791. /// <summary>
  792. /// March.
  793. /// </summary>
  794. march,
  795. /// <summary>
  796. /// April.
  797. /// </summary>
  798. april,
  799. /// <summary>
  800. /// May.
  801. /// </summary>
  802. may,
  803. /// <summary>
  804. /// June.
  805. /// </summary>
  806. june,
  807. /// <summary>
  808. /// July.
  809. /// </summary>
  810. july,
  811. /// <summary>
  812. /// August.
  813. /// </summary>
  814. august,
  815. /// <summary>
  816. /// September.
  817. /// </summary>
  818. september,
  819. /// <summary>
  820. /// October.
  821. /// </summary>
  822. october,
  823. /// <summary>
  824. /// November.
  825. /// </summary>
  826. november,
  827. /// <summary>
  828. /// December.
  829. /// </summary>
  830. december
  831. };
  832. /// <summary>
  833. /// The method tells whether the year is a leap year.
  834. /// </summary>
  835. /// <param name="year">An integer representing the Julian year.
  836. /// </param>
  837. /// <returns>A boolean which is true if <paramref name="year"/> is
  838. /// a leap year.
  839. /// </returns>
  840. public static bool is_leap_year(int year) {
  841. return CCMath.mod(year, 4) == (year > 0 ? 0 : 3);
  842. }
  843. /// <summary>
  844. /// The method returns the fixed day number of the given Julian
  845. /// date.
  846. /// </summary>
  847. /// <param name="day">An integer representing the day of the month,
  848. /// counting from 1.
  849. /// </param>
  850. /// <param name="month">An integer representing the month in the
  851. /// Julian year.
  852. /// </param>
  853. /// <param name="year">An integer representing the Julian year.
  854. /// Positive and Negative values are allowed.
  855. /// </param>
  856. /// <returns>An integer value representing the fixed day number.
  857. /// </returns>
  858. public static int fixed_from_dmy(int day, int month, int year) {
  859. int y = year < 0 ? year+1 : year;
  860. int k = epoch - 1;
  861. k += 365 * (y-1);
  862. k += CCMath.div(y-1, 4);
  863. k += CCMath.div(367*month-362, 12);
  864. if (month > 2) {
  865. k += is_leap_year(year) ? -1 : -2;
  866. }
  867. k += day;
  868. return k;
  869. }
  870. /// <summary>
  871. /// The method computes the Julian year from a fixed day number.
  872. /// </summary>
  873. /// <param name="date">The fixed day number.
  874. /// </param>
  875. /// <returns>An integer value giving the Julian year of the date.
  876. /// </returns>
  877. public static int year_from_fixed(int date) {
  878. int approx = CCMath.div(4*(date-epoch)+1464, 1461);
  879. return approx <= 0 ? approx - 1 : approx;
  880. }
  881. /// <summary>
  882. /// The method computes the Julian year and month from a fixed day
  883. /// number.
  884. /// </summary>
  885. /// <param name="month">The output value giving the Julian month.
  886. /// </param>
  887. /// <param name="year">The output value giving the Julian year.
  888. /// </param>
  889. /// <param name="date">An integer value specifying the fixed day
  890. /// number.</param>
  891. public static void my_from_fixed(out int month, out int year, int date)
  892. {
  893. year = year_from_fixed(date);
  894. int prior_days = date - fixed_from_dmy(1, (int)Month.january,
  895. year);
  896. int correction;
  897. if (date < fixed_from_dmy(1, (int)Month.march, year)) {
  898. correction = 0;
  899. } else if (is_leap_year(year)) {
  900. correction = 1;
  901. } else {
  902. correction = 2;
  903. }
  904. month = CCMath.div(12 * (prior_days + correction) + 373, 367);
  905. }
  906. /// <summary>
  907. /// The method computes the Julian year, month, and day from a
  908. /// fixed day number.
  909. /// </summary>
  910. /// <param name="day">The output value returning the day of the
  911. /// month.
  912. /// </param>
  913. /// <param name="month">The output value giving the Julian month.
  914. /// </param>
  915. /// <param name="year">The output value giving the Julian year.
  916. /// </param>
  917. /// <param name="date">An integer value specifying the fixed day
  918. /// number.</param>
  919. public static void dmy_from_fixed(out int day, out int month,
  920. out int year, int date)
  921. {
  922. my_from_fixed(out month, out year, date);
  923. day = date - fixed_from_dmy(1, month, year) + 1;
  924. }
  925. /// <summary>A method computing the Julian month from a fixed
  926. /// day number.
  927. /// </summary>
  928. /// <param name="date">An integer specifying the fixed day number.
  929. /// </param>
  930. /// <returns>An integer value representing the Julian month.
  931. /// </returns>
  932. public static int month_from_fixed(int date) {
  933. int month, year;
  934. my_from_fixed(out month, out year, date);
  935. return month;
  936. }
  937. /// <summary>
  938. /// A method computing the day of the month from a fixed day number.
  939. /// </summary>
  940. /// <param name="date">An integer specifying the fixed day number.
  941. /// </param>
  942. /// <returns>An integer value representing the day of the month.
  943. /// </returns>
  944. public static int day_from_fixed(int date) {
  945. int day;
  946. int month;
  947. int year;
  948. dmy_from_fixed(out day, out month, out year, date);
  949. return day;
  950. }
  951. /// <summary>
  952. /// The method computes the difference between two Julian dates.
  953. /// </summary>
  954. /// <param name="dayA">The integer parameter gives the day of month
  955. /// of the first date.
  956. /// </param>
  957. /// <param name="monthA">The integer parameter gives the Julian
  958. /// month of the first date.
  959. /// </param>
  960. /// <param name="yearA">The integer parameter gives the Julian
  961. /// year of the first date.
  962. /// </param>
  963. /// <param name="dayB">The integer parameter gives the day of month
  964. /// of the second date.
  965. /// </param>
  966. /// <param name="monthB">The integer parameter gives the Julian
  967. /// month of the second date.
  968. /// </param>
  969. /// <param name="yearB">The integer parameter gives the Julian
  970. /// year of the second date.
  971. /// </param>
  972. /// <returns>An integer giving the difference of days from the first
  973. /// the second date.
  974. /// </returns>
  975. public static int date_difference(int dayA, int monthA, int yearA,
  976. int dayB, int monthB, int yearB)
  977. {
  978. return fixed_from_dmy(dayB, monthB, yearB) -
  979. fixed_from_dmy(dayA, monthA, yearA);
  980. }
  981. /// <summary>
  982. /// The method computes the number of the day in the year from
  983. /// a Julian date.
  984. /// </summary>
  985. /// <param name="day">An integer representing the day of the month,
  986. /// counting from 1.
  987. /// </param>
  988. /// <param name="month">An integer representing the month in the
  989. /// Julian year.
  990. /// </param>
  991. /// <param name="year">An integer representing the Julian year.
  992. /// Negative values are allowed also.
  993. /// </param>
  994. /// <returns>An integer value giving the number of the day in the
  995. /// Julian year, counting from 1.
  996. /// </returns>
  997. public static int day_number(int day, int month, int year) {
  998. return date_difference(31, (int)Month.december, year-1,
  999. day, month, year);
  1000. }
  1001. /// <summary>
  1002. /// The method computes the days remaining in the given Julian
  1003. /// year from a Julian date.
  1004. /// </summary>
  1005. /// <param name="day">An integer representing the day of the month,
  1006. /// counting from 1.
  1007. /// </param>
  1008. /// <param name="month">An integer representing the month in the
  1009. /// Julian year.
  1010. /// </param>
  1011. /// <param name="year">An integer representing the Julian year.
  1012. /// Negative values are allowed also.
  1013. /// </param>
  1014. /// <returns>An integer value giving the number of days remaining in
  1015. /// the Julian year.
  1016. /// </returns>
  1017. public static int days_remaining(int day, int month, int year) {
  1018. return date_difference(day, month, year,
  1019. 31, (int)Month.december, year);
  1020. }
  1021. } // class CCJulianCalendar
  1022. /// <summary>
  1023. /// A class encapsulating the functions of the Hebrew calendar as static
  1024. /// methods.
  1025. /// </summary>
  1026. /// <remarks>
  1027. /// <para>
  1028. /// This class is not compatible to
  1029. /// <see cref="T:System.Globalization.HebrewCalendar"/>.
  1030. /// </para>
  1031. /// <seealso cref="T:CCFixed"/>
  1032. /// </remarks>
  1033. internal class CCHebrewCalendar {
  1034. /// <summary>An integer defining the epoch of the Hebrew calendar
  1035. /// as fixed day number.</summary>
  1036. /// <remarks>The epoch is October 10, 3761 B.C.E. (Julian).</remarks>
  1037. const int epoch = -1373427;
  1038. /// <summary>The enumeration defines the months of the Gregorian
  1039. /// calendar.
  1040. /// </summary>
  1041. /// <remarks>
  1042. /// The enumaration differs from .NET which defines Tishri as month 1.
  1043. /// </remarks>
  1044. public enum Month {
  1045. /// <summary>
  1046. /// Nisan.
  1047. /// </summary>
  1048. nisan = 1,
  1049. /// <summary>
  1050. /// Iyyar.
  1051. /// </summary>
  1052. iyyar,
  1053. /// <summary>
  1054. /// Sivan.
  1055. /// </summary>
  1056. sivan,
  1057. /// <summary>
  1058. /// Tammuz.
  1059. /// </summary>
  1060. tammuz,
  1061. /// <summary>
  1062. /// Av.
  1063. /// </summary>
  1064. av,
  1065. /// <summary>
  1066. /// Elul.
  1067. /// </summary>
  1068. elul,
  1069. /// <summary>
  1070. /// Tishri.
  1071. /// </summary>
  1072. tishri,
  1073. /// <summary>
  1074. /// Heshvan.
  1075. /// </summary>
  1076. heshvan,
  1077. /// <summary>
  1078. /// Kislev.
  1079. /// </summary>
  1080. kislev,
  1081. /// <summary>
  1082. /// Teveth.
  1083. /// </summary>
  1084. teveth,
  1085. /// <summary>
  1086. /// Shevat.
  1087. /// </summary>
  1088. shevat,
  1089. /// <summary>
  1090. /// Adar.
  1091. /// </summary>
  1092. adar,
  1093. /// <summary>
  1094. /// Adar I. Only in years with Adar II.
  1095. /// </summary>
  1096. adar_I = 12,
  1097. /// <summary>
  1098. /// Adar II. Only in years wirh Adar I.
  1099. /// </summary>
  1100. adar_II = 13,
  1101. };
  1102. /// <summary>
  1103. /// The method tells whether the year is a leap year.
  1104. /// </summary>
  1105. /// <param name="year">An integer representing the Hebrew year.
  1106. /// </param>
  1107. /// <returns>A boolean which is true if <paramref name="year"/> is
  1108. /// a leap year.
  1109. /// </returns>
  1110. public static bool is_leap_year(int year) {
  1111. return CCMath.mod(7*year+1, 19) < 7;
  1112. }
  1113. /// <summary>
  1114. /// The Method gives the number of the last month in a year, which
  1115. /// is equal with the number of month in a Hebrew year.
  1116. /// </summary>
  1117. /// <param name="year">An integer representing the Hebrew year.
  1118. /// </param>
  1119. /// <returns>An integer giving the number of the last month of the
  1120. /// Hebrew year, which is the same as the numbers of month in the
  1121. /// year.
  1122. /// </returns>
  1123. public static int last_month_of_year(int year) {
  1124. return is_leap_year(year) ? 13 : 12;
  1125. }
  1126. /// <summary>The method is a helper function.</summary>
  1127. /// <param name="year">An integer specifying the Hebrew year.
  1128. /// </param>
  1129. /// <returns>An integer representing the number of elapsed days
  1130. /// until the Hebrew year.</returns>
  1131. public static int elapsed_days(int year) {
  1132. int months_elapsed = CCMath.div(235*year-234, 19);
  1133. int r;
  1134. int d = CCMath.div_mod(out r, months_elapsed, 1080);
  1135. int parts_elapsed = 204 + 793 * r;
  1136. int hours_elapsed = 11 + 12 * months_elapsed +
  1137. 793 * d + CCMath.div(parts_elapsed, 1080);
  1138. int day = 29*months_elapsed + CCMath.div(hours_elapsed, 24);
  1139. if (CCMath.mod(3*(day+1), 7) < 3) {
  1140. day += 1;
  1141. }
  1142. return day;
  1143. }
  1144. /// <summary>A method computing the delay of new year for the given
  1145. /// Hebrew year.
  1146. /// </summary>
  1147. /// <param name="year">An integer that gives the Hebrew year.
  1148. /// </param>
  1149. /// <returns>The new year delay in days of the given Hebrew year.
  1150. /// </returns>
  1151. public static int new_year_delay(int year) {
  1152. int ny1 = elapsed_days(year);
  1153. int ny2 = elapsed_days(year+1);
  1154. if (ny2 - ny1 == 356) {
  1155. return 2;
  1156. }
  1157. int ny0 = elapsed_days(year-1);
  1158. if (ny1 - ny0 == 382) {
  1159. return 1;
  1160. }
  1161. return 0;
  1162. }
  1163. /// <summary>
  1164. /// The method computes the last day of month (nummer of days in a
  1165. /// month) of the given Hebrew year.
  1166. /// </summary>
  1167. /// <param name="month">The Hebrew month, allowed value between
  1168. /// One and Thirteen.
  1169. /// </param>
  1170. /// <param name="year">An integer that gives the Hebrew year.
  1171. /// </param>
  1172. /// <returns>The number of the last day of the month of the given
  1173. /// Hebrew year, which gives automatically the number of days in the
  1174. /// month.
  1175. /// </returns>
  1176. /// <exception cref="T:System.ArgumentOutOfRange.Exception">
  1177. /// The exception is thrown if month not between One and Thirteen.
  1178. /// </exception>
  1179. public static int last_day_of_month(int month, int year) {
  1180. if (month < 1 || month > 13)
  1181. throw new System.ArgumentOutOfRangeException("month",
  1182. "Month should be between One and Thirteen.");
  1183. switch (month) {
  1184. case 2: return 29;
  1185. case 4: return 29;
  1186. case 6: return 29;
  1187. case 8:
  1188. if (!long_heshvan(year))
  1189. return 29;
  1190. break;
  1191. case 9:
  1192. if (short_kislev(year))
  1193. return 29;
  1194. break;
  1195. case 10: return 29;
  1196. case 12:
  1197. if (!is_leap_year(year))
  1198. return 29;
  1199. break;
  1200. case 13: return 29;
  1201. }
  1202. return 30;
  1203. }
  1204. /// <summary>
  1205. /// The functions checks whether the month Heshvan is a long one
  1206. /// in the given Hebrew year.
  1207. /// </summary>
  1208. /// <param name="year">An integer that gives the Hebrew year.
  1209. /// </param>
  1210. /// <returns>A boolean value: true if there is a long Heshvan
  1211. /// in the given Hebrew year; false otherwise.
  1212. /// </returns>
  1213. public static bool long_heshvan(int year) {
  1214. return CCMath.mod(days_in_year(year), 10) == 5;
  1215. }
  1216. /// <summary>
  1217. /// The functions checks whether the month Kislev is a short one
  1218. /// in the given Hebrew year.
  1219. /// </summary>
  1220. /// <param name="year">An integer that gives the Hebrew year.
  1221. /// </param>
  1222. /// <returns>A boolean value: true if there is a short Kislev
  1223. /// in the given Hebrew year; false otherwise.
  1224. /// </returns>
  1225. public static bool short_kislev(int year) {
  1226. return CCMath.mod(days_in_year(year), 10) == 3;
  1227. }
  1228. /// <summary>
  1229. /// The functions gives the number of days in the specified Hebrew
  1230. /// year.
  1231. /// </summary>
  1232. /// <param name="year">An integer that gives the Hebrew year.
  1233. /// </param>
  1234. /// <returns>The days of the Hebrew year as integer.
  1235. /// </returns>
  1236. public static int days_in_year(int year) {
  1237. return fixed_from_dmy(1, 7, year+1) -
  1238. fixed_from_dmy(1, 7, year);
  1239. }
  1240. /// <summary>
  1241. /// The method returns the fixed day number of the given Hebrew
  1242. /// date.
  1243. /// </summary>
  1244. /// <param name="day">An integer representing the day of the month,
  1245. /// counting from 1.
  1246. /// </param>
  1247. /// <param name="month">An integer representing the month in the
  1248. /// Hebrew year.
  1249. /// </param>
  1250. /// <param name="year">An integer representing the Hebrew year.
  1251. /// Non-positive values are allowed also.
  1252. /// </param>
  1253. /// <returns>An integer value representing the fixed day number.
  1254. /// </returns>
  1255. public static int fixed_from_dmy(int day, int month, int year) {
  1256. int m;
  1257. int k = epoch-1;
  1258. k += elapsed_days(year);
  1259. k += new_year_delay(year);
  1260. if (month < 7) {
  1261. int l = last_month_of_year(year);
  1262. for (m = 7; m <= l; m++) {
  1263. k += last_day_of_month(m, year);
  1264. }
  1265. for (m = 1; m < month; m++) {
  1266. k += last_day_of_month(m, year);
  1267. }
  1268. }
  1269. else {
  1270. for (m = 7; m < month; m++) {
  1271. k += last_day_of_month(m, year);
  1272. }
  1273. }
  1274. k += day;
  1275. return k;
  1276. }
  1277. /// <summary>
  1278. /// The method computes the Hebrew year from a fixed day number.
  1279. /// </summary>
  1280. /// <param name="date">The fixed day number.
  1281. /// </param>
  1282. /// <returns>An integer value giving the Hebrew year of the date.
  1283. /// </returns>
  1284. public static int year_from_fixed(int date) {
  1285. int approx = (int)System.Math.Floor(
  1286. ((double)(date - epoch))/(35975351.0/98496.0));
  1287. int y;
  1288. for (y = approx; date >= fixed_from_dmy(1, 7, y); y++) {}
  1289. return y-1;
  1290. }
  1291. /// <summary>
  1292. /// The method computes the Hebrew year and month from a fixed day
  1293. /// number.
  1294. /// </summary>
  1295. /// <param name="month">The output value giving the Hebrew month.
  1296. /// </param>
  1297. /// <param name="year">The output value giving the Hebrew year.
  1298. /// </param>
  1299. /// <param name="date">An integer value specifying the fixed day
  1300. /// number.</param>
  1301. public static void my_from_fixed(out int month, out int year,
  1302. int date)
  1303. {
  1304. year = year_from_fixed(date);
  1305. int start = date < fixed_from_dmy(1, 1, year) ? 7 : 1;
  1306. for (month = start;
  1307. date > fixed_from_dmy(last_day_of_month(month, year),
  1308. month, year);
  1309. month++)
  1310. {}
  1311. }
  1312. /// <summary>
  1313. /// The method computes the Hebrew year, month, and day from a
  1314. /// fixed day number.
  1315. /// </summary>
  1316. /// <param name="day">The output value returning the day of the
  1317. /// month.
  1318. /// </param>
  1319. /// <param name="month">The output value giving the Hebrew month.
  1320. /// </param>
  1321. /// <param name="year">The output value giving the Hebrew year.
  1322. /// </param>
  1323. /// <param name="date">An integer value specifying the fixed day
  1324. /// number.</param>
  1325. public static void dmy_from_fixed(out int day, out int month,
  1326. out int year, int date)
  1327. {
  1328. my_from_fixed(out month, out year, date);
  1329. day = date - fixed_from_dmy(1, month, year) + 1;
  1330. }
  1331. /// <summary>A method computing the Hebrew month from a fixed
  1332. /// day number.
  1333. /// </summary>
  1334. /// <param name="date">An integer specifying the fixed day number.
  1335. /// </param>
  1336. /// <returns>An integer value representing the Hebrew month.
  1337. /// </returns>
  1338. public static int month_from_fixed(int date) {
  1339. int month, year;
  1340. my_from_fixed(out month, out year, date);
  1341. return month;
  1342. }
  1343. /// <summary>
  1344. /// A method computing the day of the month from a fixed day number.
  1345. /// </summary>
  1346. /// <param name="date">An integer specifying the fixed day number.
  1347. /// </param>
  1348. /// <returns>An integer value representing the day of the month.
  1349. /// </returns>
  1350. public static int day_from_fixed(int date) {
  1351. int day, month, year;
  1352. dmy_from_fixed(out day, out month, out year, date);
  1353. return day;
  1354. }
  1355. /// <summary>
  1356. /// The method computes the difference between two Hebrew dates.
  1357. /// </summary>
  1358. /// <param name="dayA">The integer parameter gives the day of month
  1359. /// of the first date.
  1360. /// </param>
  1361. /// <param name="monthA">The integer parameter gives the Hebrew
  1362. /// month of the first date.
  1363. /// </param>
  1364. /// <param name="yearA">The integer parameter gives the Hebrew
  1365. /// year of the first date.
  1366. /// </param>
  1367. /// <param name="dayB">The integer parameter gives the day of month
  1368. /// of the second date.
  1369. /// </param>
  1370. /// <param name="monthB">The integer parameter gives the Hebrew
  1371. /// month of the second date.
  1372. /// </param>
  1373. /// <param name="yearB">The integer parameter gives the Hebrew
  1374. /// year of the second date.
  1375. /// </param>
  1376. /// <returns>An integer giving the difference of days from the first
  1377. /// the second date.
  1378. /// </returns>
  1379. public static int date_difference(int dayA, int monthA, int yearA,
  1380. int dayB, int monthB, int yearB)
  1381. {
  1382. return fixed_from_dmy(dayB, monthB, yearB) -
  1383. fixed_from_dmy(dayA, monthA, yearA);
  1384. }
  1385. /// <summary>
  1386. /// The method computes the number of the day in the year from
  1387. /// a Hebrew date.
  1388. /// </summary>
  1389. /// <param name="day">An integer representing the day of the month,
  1390. /// counting from 1.
  1391. /// </param>
  1392. /// <param name="month">An integer representing the month in the
  1393. /// Hebrew year.
  1394. /// </param>
  1395. /// <param name="year">An integer representing the Hebrew year.
  1396. /// </param>
  1397. /// <returns>An integer value giving the number of the day in the
  1398. /// Hebrew year, counting from 1.
  1399. /// </returns>
  1400. public static int day_number(int day, int month, int year) {
  1401. return date_difference(1, 7, year,
  1402. day, month, year) + 1;
  1403. }
  1404. /// <summary>
  1405. /// The method computes the days remaining in the given Hebrew
  1406. /// year from a Hebrew date.
  1407. /// </summary>
  1408. /// <param name="day">An integer representing the day of the month,
  1409. /// counting from 1.
  1410. /// </param>
  1411. /// <param name="month">An integer representing the month in the
  1412. /// Hebrew year.
  1413. /// </param>
  1414. /// <param name="year">An integer representing the Hebrew year.
  1415. /// </param>
  1416. /// <returns>An integer value giving the number of days remaining in
  1417. /// the Hebrew year.
  1418. /// </returns>
  1419. public static int days_remaining(int day, int month, int year) {
  1420. return date_difference(day, month, year,
  1421. 1, 7, year+1)-1;
  1422. }
  1423. } // class HebrewCalendar
  1424. /// <summary>
  1425. /// A class encapsulating the functions of the Islamic calendar as static
  1426. /// methods.
  1427. /// </summary>
  1428. /// <remarks>
  1429. /// <para>There is no difference here in using Hijri or Islamic calendar.
  1430. /// </para>
  1431. /// <para>The epoch of the Islamic calendar isn't fixed, because we cannot
  1432. /// surely say today, when the crescent of the new moon has been observed
  1433. /// around the July 16, 622 C.E. Julian. Even today the start and end of
  1434. /// the month Ramadan is defined by religous authorities. So the calendar
  1435. /// can be offset by two days.
  1436. /// </para>
  1437. /// <para>
  1438. /// We don't support the offset here, however we changed the epoch from
  1439. /// "Calendrical Calculations" to value, that .Net seems to be using.
  1440. /// </para>
  1441. /// <para>
  1442. /// This class is not compatible to
  1443. /// <see cref="T:System.Globalization.HijriCalendar"/>.
  1444. /// </para>
  1445. /// <seealso cref="T:CCFixed"/>
  1446. /// </remarks>
  1447. public class CCHijriCalendar {
  1448. /// <summary>An integer defining the epoch of the Gregorian calendar
  1449. /// as fixed day number.</summary>
  1450. /// <remarks>
  1451. /// <para>
  1452. /// The epoch is given as 16 July 622 C.E. Julian (R.D. 227015)
  1453. /// in Calendrical Calculations, the approximate date of
  1454. /// the emigration of
  1455. /// Muhammed to Medina. However there is no way to determine today
  1456. /// the observation of the crescent of the new moon in July 622 C.E.
  1457. /// (Julian). So there is some variability in the epoch.
  1458. /// Religous authorities determine the epoch by observing the
  1459. /// crescent of the new moon for the month Ramadan, so there might
  1460. /// be an offsets by two days of the epoch.
  1461. /// </para>
  1462. /// <para>Windows
  1463. /// supports an AddHijriDate parameter in the registry to adapt
  1464. /// for it. It seems that the .NET implementation of
  1465. /// HijriCalendar uses an epoch of 227014, so we use it here. The
  1466. /// ArgumentOutOfRangeException gives July, 18 622 as epoch,
  1467. /// which is 227014 supporting our theory.
  1468. /// </para>
  1469. /// </remarks>
  1470. const int epoch = 227014;
  1471. /// <summary>The enumeration defines the months of the Islamic
  1472. /// calendar.
  1473. /// </summary>
  1474. public enum Month {
  1475. /// <summary>
  1476. /// Muharram.
  1477. /// </summary>
  1478. muharram = 1,
  1479. /// <summary>
  1480. /// Safar.
  1481. /// </summary>
  1482. safar,
  1483. /// <summary>
  1484. /// Rabi I.
  1485. /// </summary>
  1486. rabi_I,
  1487. /// <summary>
  1488. /// Rabi II.
  1489. /// </summary>
  1490. rabi_II,
  1491. /// <summary>
  1492. /// Jumada I.
  1493. /// </summary>
  1494. jumada_I,
  1495. /// <summary>
  1496. /// Jumada II.
  1497. /// </summary>
  1498. jumada_II,
  1499. /// <summary>
  1500. /// Rajab.
  1501. /// </summary>
  1502. rajab,
  1503. /// <summary>
  1504. /// Shaban.
  1505. /// </summary>
  1506. shaban,
  1507. /// <summary>
  1508. /// Ramadan.
  1509. /// </summary>
  1510. ramadan,
  1511. /// <summary>
  1512. /// Shawwal.
  1513. /// </summary>
  1514. shawwal,
  1515. /// <summary>
  1516. /// Dhu Al-Quada.
  1517. /// </summary>
  1518. dhu_al_quada,
  1519. /// <summary>
  1520. /// Dhu Al-Hijja.
  1521. /// </summary>
  1522. dhu_al_hijja,
  1523. };
  1524. /// <summary>
  1525. /// The method tells whether the year is a leap year.
  1526. /// </summary>
  1527. /// <param name="year">An integer representing the Islamic year.
  1528. /// </param>
  1529. /// <returns>A boolean which is true if <paramref name="year"/> is
  1530. /// a leap year.
  1531. /// </returns>
  1532. public static bool is_leap_year(int year) {
  1533. return CCMath.mod(14+11*year, 30) < 11;
  1534. }
  1535. /// <summary>
  1536. /// The method returns the fixed day number of the given Islamic
  1537. /// date.
  1538. /// </summary>
  1539. /// <param name="day">An integer representing the day of the month,
  1540. /// counting from 1.
  1541. /// </param>
  1542. /// <param name="month">An integer representing the month in the
  1543. /// Islamic year.
  1544. /// </param>
  1545. /// <param name="year">An integer representing the Islamic year.
  1546. /// Non-positive values are allowed also.
  1547. /// </param>
  1548. /// <returns>An integer value representing the fixed day number.
  1549. /// </returns>
  1550. public static int fixed_from_dmy(int day, int month, int year) {
  1551. int k = epoch - 1;
  1552. k += 354 * (year-1);
  1553. k += CCMath.div(3+11*year, 30);
  1554. k += (int)System.Math.Ceiling(29.5 * (double)(month-1));
  1555. k += day;
  1556. return k;
  1557. }
  1558. /// <summary>
  1559. /// The method computes the Islamic year from a fixed day number.
  1560. /// </summary>
  1561. /// <param name="date">The fixed day number.
  1562. /// </param>
  1563. /// <returns>An integer value giving the Islamic year of the date.
  1564. /// </returns>
  1565. public static int year_from_fixed(int date) {
  1566. return CCMath.div(30*(date-epoch)+10646, 10631);
  1567. }
  1568. /// <summary>
  1569. /// The method computes the Islamic year and month from a fixed day
  1570. /// number.
  1571. /// </summary>
  1572. /// <param name="month">The output value giving the Islamic month.
  1573. /// </param>
  1574. /// <param name="year">The output value giving the Islamic year.
  1575. /// </param>
  1576. /// <param name="date">An integer value specifying the fixed day
  1577. /// number.</param>
  1578. public static void my_from_fixed(out int month, out int year, int date)
  1579. {
  1580. year = year_from_fixed(date);
  1581. int m = 1+(int)System.Math.Ceiling(
  1582. ((double)(date-29-fixed_from_dmy(1,1,year)))/29.5);
  1583. month = m < 12 ? m : 12;
  1584. }
  1585. /// <summary>
  1586. /// The method computes the Islamic year, month, and day from a
  1587. /// fixed day number.
  1588. /// </summary>
  1589. /// <param name="day">The output value returning the day of the
  1590. /// month.
  1591. /// </param>
  1592. /// <param name="month">The output value giving the Islamic month.
  1593. /// </param>
  1594. /// <param name="year">The output value giving the Islamic year.
  1595. /// </param>
  1596. /// <param name="date">An integer value specifying the fixed day
  1597. /// number.</param>
  1598. public static void dmy_from_fixed(out int day, out int month,
  1599. out int year, int date)
  1600. {
  1601. my_from_fixed(out month, out year, date);
  1602. day = date - fixed_from_dmy(1, month, year) + 1;
  1603. }
  1604. /// <summary>A method computing the Islamic month from a fixed
  1605. /// day number.
  1606. /// </summary>
  1607. /// <param name="date">An integer specifying the fixed day number.
  1608. /// </param>
  1609. /// <returns>An integer value representing the Islamic month.
  1610. /// </returns>
  1611. public static int month_from_fixed(int date) {
  1612. int month, year;
  1613. my_from_fixed(out month, out year, date);
  1614. return month;
  1615. }
  1616. /// <summary>
  1617. /// A method computing the day of the month from a fixed day number.
  1618. /// </summary>
  1619. /// <param name="date">An integer specifying the fixed day number.
  1620. /// </param>
  1621. /// <returns>An integer value representing the day of the month.
  1622. /// </returns>
  1623. public static int day_from_fixed(int date) {
  1624. int day;
  1625. int month;
  1626. int year;
  1627. dmy_from_fixed(out day, out month, out year, date);
  1628. return day;
  1629. }
  1630. /// <summary>
  1631. /// The method computes the difference between two Islamic dates.
  1632. /// </summary>
  1633. /// <param name="dayA">The integer parameter gives the day of month
  1634. /// of the first date.
  1635. /// </param>
  1636. /// <param name="monthA">The integer parameter gives the Islamic
  1637. /// month of the first date.
  1638. /// </param>
  1639. /// <param name="yearA">The integer parameter gives the Islamic
  1640. /// year of the first date.
  1641. /// </param>
  1642. /// <param name="dayB">The integer parameter gives the day of month
  1643. /// of the second date.
  1644. /// </param>
  1645. /// <param name="monthB">The integer parameter gives the Islamic
  1646. /// month of the second date.
  1647. /// </param>
  1648. /// <param name="yearB">The integer parameter gives the Islamic
  1649. /// year of the second date.
  1650. /// </param>
  1651. /// <returns>An integer giving the difference of days from the first
  1652. /// the second date.
  1653. /// </returns>
  1654. public static int date_difference(int dayA, int monthA, int yearA,
  1655. int dayB, int monthB, int yearB)
  1656. {
  1657. return fixed_from_dmy(dayB, monthB, yearB) -
  1658. fixed_from_dmy(dayA, monthA, yearA);
  1659. }
  1660. /// <summary>
  1661. /// The method computes the number of the day in the year from
  1662. /// a Islamic date.
  1663. /// </summary>
  1664. /// <param name="day">An integer representing the day of the month,
  1665. /// counting from 1.
  1666. /// </param>
  1667. /// <param name="month">An integer representing the month in the
  1668. /// Islamic year.
  1669. /// </param>
  1670. /// <param name="year">An integer representing the Islamic year.
  1671. /// </param>
  1672. /// <returns>An integer value giving the number of the day in the
  1673. /// Islamic year, counting from 1.
  1674. /// </returns>
  1675. public static int day_number(int day, int month, int year) {
  1676. return date_difference(31, 12, year-1, day, month, year);
  1677. }
  1678. /// <summary>
  1679. /// The method computes the days remaining in the given Islamic
  1680. /// year from a Islamic date.
  1681. /// </summary>
  1682. /// <param name="day">An integer representing the day of the month,
  1683. /// counting from 1.
  1684. /// </param>
  1685. /// <param name="month">An integer representing the month in the
  1686. /// Islamic year.
  1687. /// </param>
  1688. /// <param name="year">An integer representing the Islamic year.
  1689. /// Non-positive values are allowed also.
  1690. /// </param>
  1691. /// <returns>An integer value giving the number of days remaining in
  1692. /// the Islamic year.
  1693. /// </returns>
  1694. public static int days_remaining(int day, int month, int year) {
  1695. return date_difference(day, month, year,31, 12, year);
  1696. }
  1697. } // class CCHijriCalendar
  1698. /// <summary>
  1699. /// A class that supports the Gregorian based calendars with other eras
  1700. /// (e.g. <see cref="T:System.Gloablization.JapaneseCalendar"/>).
  1701. /// </summary>
  1702. [System.Serializable]
  1703. public class CCGregorianEraHandler {
  1704. /// <summary>
  1705. /// A struct that represents a single era.
  1706. /// </summary>
  1707. [System.Serializable]
  1708. struct Era {
  1709. /// <summary>
  1710. /// The integer number identifying the era.
  1711. /// </summary>
  1712. private int _nr;
  1713. /// <value>
  1714. /// A get-only property that gives the era integer number.
  1715. /// </value>
  1716. public int Nr { get { return _nr; } }
  1717. /// <summary>This integer gives the first day of the era as
  1718. /// fixed day number.
  1719. /// </summary>
  1720. private int _start; // inclusive
  1721. /// <summary>
  1722. /// This integer gives the gregorian year of the
  1723. /// <see cref="M:_start"/> value.
  1724. /// </summary>
  1725. private int _gregorianYearStart;
  1726. /// <summary>
  1727. /// This integer gives the last day of the era as fixed day
  1728. /// number.
  1729. /// </summary>
  1730. private int _end; // inclusive
  1731. /// <summary>
  1732. /// This integer gives the largest year number of this era.
  1733. /// </summary>
  1734. private int _maxYear;
  1735. /// <summary>
  1736. /// This constructor creates the era structure.
  1737. /// </summary>
  1738. /// <param name="nr">The integer number of the era.
  1739. /// </param>
  1740. /// <param name="start">The fixed day number defining the
  1741. /// first day of the era.
  1742. /// </param>
  1743. /// <param name="end">The fixed day number that defines the
  1744. /// last day of the era.
  1745. /// </param>
  1746. public Era(int nr, int start, int end) {
  1747. if (nr == 0)
  1748. throw new System.ArgumentException(
  1749. "Era number shouldn't be zero.");
  1750. _nr = nr;
  1751. if (start > end) {
  1752. throw new System.ArgumentException(
  1753. "Era should start before end.");
  1754. }
  1755. _start = start;
  1756. _end = end;
  1757. _gregorianYearStart =
  1758. CCGregorianCalendar.year_from_fixed(_start);
  1759. int gregorianYearEnd =
  1760. CCGregorianCalendar.year_from_fixed(_end);
  1761. _maxYear = gregorianYearEnd - _gregorianYearStart + 1;
  1762. }
  1763. /// <summary>
  1764. /// This method computes the Gregorian year from the year
  1765. /// of this era.
  1766. /// </summary>
  1767. /// <param name="year">An integer giving the year in the
  1768. /// era.
  1769. /// </param>
  1770. /// <returns>
  1771. /// The Gregorian year as integer.
  1772. /// </returns>
  1773. /// <exception cref="T:System.ArgumentOutOfRangeException">
  1774. /// The exception is thrown if the year isn't valid in this
  1775. /// era.
  1776. /// </exception>
  1777. public int GregorianYear(int year) {
  1778. if (year < 1 || year > _maxYear) {
  1779. System.IO.StringWriter sw =
  1780. new System.IO.StringWriter();
  1781. sw.Write(
  1782. "Valid Values are between " +
  1783. "{0} and {1}, inclusive.",
  1784. 1, _maxYear);
  1785. throw new System.ArgumentOutOfRangeException(
  1786. "year", sw.ToString());
  1787. }
  1788. return year + _gregorianYearStart - 1;
  1789. }
  1790. /// <summary>
  1791. /// This function checks wether the given fixed day number is
  1792. /// ion the time span of the era.
  1793. /// </summary>
  1794. /// <param name="date">An integer giving the fixed day
  1795. /// number.
  1796. /// </param>
  1797. /// <returns>A boolean: true if the argument is in the time
  1798. /// span of the era.
  1799. /// </returns>
  1800. public bool Covers(int date) {
  1801. return _start <= date && date <= _end;
  1802. }
  1803. /// <summary>
  1804. /// This function returns the year of the era and sets
  1805. /// the era in an output parameter.
  1806. /// </summary>
  1807. /// <param name="era">An output parameter returning the
  1808. /// era number.
  1809. /// </param>
  1810. /// <param name="date">An integer giving the fixed day
  1811. /// number.
  1812. /// </param>
  1813. /// <returns>An integer giving the year of the era.
  1814. /// </returns>
  1815. /// <exception cref="T:System.ArgumentOutOfRangeException">
  1816. /// The exception is thrown if date is outside of the time
  1817. /// span of the era.
  1818. /// </exception>
  1819. public int EraYear(out int era, int date) {
  1820. if (!Covers(date))
  1821. throw new System.ArgumentOutOfRangeException(
  1822. "date",
  1823. "Time was out of Era range.");
  1824. int gregorianYear =
  1825. CCGregorianCalendar.year_from_fixed(date);
  1826. era = _nr;
  1827. return gregorianYear - _gregorianYearStart + 1;
  1828. }
  1829. } // struct Era
  1830. /// <summary>
  1831. /// A private member storing the eras in a
  1832. /// <see cref="T:System.Collections.SortedList"/>.
  1833. /// </summary>
  1834. private SortedList _Eras;
  1835. /// <value>
  1836. /// The property returns the era numbers as an array of integers.
  1837. /// </value>
  1838. public int[] Eras {
  1839. get {
  1840. int[] a = new int[_Eras.Count];
  1841. for (int i = 0; i < _Eras.Count; i++) {
  1842. Era e = (Era)_Eras.GetByIndex(i);
  1843. a[i] = e.Nr;
  1844. }
  1845. return a;
  1846. }
  1847. }
  1848. /// <summary>
  1849. /// Constructor.
  1850. /// </summary>
  1851. public CCGregorianEraHandler() {
  1852. _Eras = new SortedList();
  1853. }
  1854. /// <summary>
  1855. /// Method adds an era to the GregorianEraHandler instance.
  1856. /// </summary>
  1857. /// <param name="nr">The integer number of the era.
  1858. /// </param>
  1859. /// <param name="rd_start">The fixed day number defining the
  1860. /// first day of the era.
  1861. /// </param>
  1862. /// <param name="rd_end">The fixed day number that defines the
  1863. /// last day of the era.
  1864. /// </param>
  1865. public void appendEra(int nr, int rd_start, int rd_end) {
  1866. Era era = new Era(nr, rd_start, rd_end);
  1867. _Eras[(System.Object)nr] = era;
  1868. }
  1869. /// <summary>
  1870. /// Method adds a yet not-ended era to the GregorianEraHandler
  1871. /// instance.
  1872. /// </summary>
  1873. /// <param name="nr">The integer number of the era.
  1874. /// </param>
  1875. /// <param name="rd_start">The fixed day number defining the
  1876. /// first day of the era.
  1877. /// </param>
  1878. public void appendEra(int nr, int rd_start) {
  1879. appendEra(nr, rd_start,
  1880. CCFixed.FromDateTime(DateTime.MaxValue));
  1881. }
  1882. /// <summary>
  1883. /// This method computes the Gregorian year from the year
  1884. /// of the given era.
  1885. /// </summary>
  1886. /// <param name="year">An integer giving the year in the
  1887. /// era.
  1888. /// </param>
  1889. /// <param name="era">An integer giving the era number.
  1890. /// </param>
  1891. /// <returns>
  1892. /// The Gregorian year as integer.
  1893. /// </returns>
  1894. /// <exception cref="T:System.ArgumentOutOfRangeException">
  1895. /// The exception is thrown if the year isn't valid in this
  1896. /// era.
  1897. /// </exception>
  1898. public int GregorianYear(int year, int era) {
  1899. Era e = (Era)_Eras[(System.Object)era];
  1900. return e.GregorianYear(year);
  1901. }
  1902. /// <summary>
  1903. /// This function returns the year of the era and sets
  1904. /// the era in an output parameter.
  1905. /// </summary>
  1906. /// <param name="era">An output parameter returning the
  1907. /// era number.
  1908. /// </param>
  1909. /// <param name="date">An integer giving the fixed day
  1910. /// number.
  1911. /// </param>
  1912. /// <returns>An integer giving the year of the era.
  1913. /// </returns>
  1914. /// <exception cref="T:System.ArgumentOutOfRangeException">
  1915. /// The exception is thrown if the fixed day number is outside of the
  1916. /// time spans of all eras.
  1917. /// </exception>
  1918. public int EraYear(out int era, int date)
  1919. {
  1920. IList list = _Eras.GetValueList();
  1921. foreach (Era e in list) {
  1922. if (e.Covers(date))
  1923. return e.EraYear(out era, date);
  1924. }
  1925. throw new System.ArgumentOutOfRangeException("date",
  1926. "Time value was out of era range.");
  1927. }
  1928. /// <summary>
  1929. /// The method checks whether a given
  1930. /// <see cref="T:System.DateTime"/> is covered by any era.
  1931. /// </summary>
  1932. /// <param name="time">A
  1933. /// <see cref="T:System.DateTime"/> giving the date and time.
  1934. /// </param>
  1935. /// <exception cref="T:System.ArgumentOutOfRangeException">
  1936. /// The exception is thrown if the argument isn't inside the time
  1937. /// span of any era.
  1938. /// </exception>
  1939. public void CheckDateTime(System.DateTime time) {
  1940. int date = CCFixed.FromDateTime(time);
  1941. if (!ValidDate(date))
  1942. throw new System.ArgumentOutOfRangeException("time",
  1943. "Time value was out of era range.");
  1944. }
  1945. /// <summary>
  1946. /// The method tests whether a given
  1947. /// fixed day number is covered by any era.
  1948. /// </summary>
  1949. /// <param name="date">An integer representing the fixed day number.
  1950. /// </param>
  1951. /// <returns> A boolean is returned: true if the argument is inside
  1952. /// the time span of one era; false otherwise.
  1953. /// </returns>
  1954. public bool ValidDate(int date) {
  1955. IList list = _Eras.GetValueList();
  1956. foreach (Era e in list) {
  1957. if (e.Covers(date))
  1958. return true;
  1959. }
  1960. return false;
  1961. }
  1962. /// <summary>
  1963. /// The method tests, whether the era number does exist.
  1964. /// </summary>
  1965. /// <param name="era">An integer giving the era number.
  1966. /// </param>
  1967. /// <returns>A boole value: True if the era number does exist;
  1968. /// false otherwise.
  1969. /// </returns>
  1970. public bool ValidEra(int era) {
  1971. return _Eras.Contains((System.Object)era);
  1972. }
  1973. } // class CCGregorianEraHandler
  1974. } // namespace System.Globalization