PageRenderTime 58ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/corlib/System.Globalization/CalendricalCalculations.cs

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