Calendar.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917
  1. // Calendar.cs
  2. //
  3. // (C) Ulrich Kunitz 2002
  4. //
  5. namespace System.Globalization {
  6. using System;
  7. using System.IO;
  8. /// <remarks>
  9. /// The class serves as a base class for calendar classes.
  10. /// </remarks>
  11. [Serializable]
  12. public abstract class Calendar {
  13. /// <value>An protected integer property that gives the number of
  14. /// days in a week. It might be overridden.</value>
  15. internal virtual int M_DaysInWeek
  16. {
  17. get { return 7; }
  18. }
  19. /// <summary>
  20. /// The protected method creates the string used in the
  21. /// <see cref="T:System.ArgumentOutOfRangeException"/>
  22. /// </summary>
  23. /// <param name="a">An object that represents the smallest
  24. /// allowable value.</param>
  25. /// <param name="b">An object that represents the greatest allowable
  26. /// value.</param>
  27. /// <returns>The string used in the
  28. /// <see cref="T:System.ArgumentOutOfRangeException"/>
  29. /// </returns>
  30. internal string M_ValidValues(object a, object b)
  31. {
  32. StringWriter sw = new StringWriter();
  33. sw.Write("Valid values are between {0} and {1}, inclusive.",
  34. a, b);
  35. return sw.ToString();
  36. }
  37. /// <summary>
  38. /// The protected method checks wether the parameter
  39. /// <paramref name="arg"/> is in the allowed range.
  40. /// </summary>
  41. /// <param name="param">A string that gives the name of the
  42. /// parameter to check.</param>
  43. /// <param name="arg">An integer that gives the value to check.
  44. /// </param>
  45. /// <param name="a">An integer that represents the smallest allowed
  46. /// value.</param>
  47. /// <param name="b">An integer that represents the greatest allowed
  48. /// value.</param>
  49. /// <exception cref="T:System.ArgumentOutOfRangeException">
  50. /// The exception is thrown, if the <paramref name="arg"/> is outside
  51. /// the allowed range.
  52. /// </exception>
  53. internal void M_ArgumentInRange(string param, int arg, int a, int b)
  54. {
  55. if (a <= arg && arg <= b)
  56. return;
  57. throw new ArgumentOutOfRangeException(param, M_ValidValues(a, b));
  58. }
  59. /// <summary>
  60. /// The protected method, that checks whether
  61. /// <paramref name="hour"/>, <paramref name="minute"/>,
  62. /// <paramref name="second"/>, and <parameref name="millisecond"/>
  63. /// are in their valid ranges
  64. /// </summary>
  65. /// <param name="hour">An integer that represents a hour,
  66. /// should be between 0 and 23.</param>
  67. /// <param name="minute">An integer that represents a minute,
  68. /// should be between 0 and 59.</param>
  69. /// <param name="second">An integer that represents a second,
  70. /// should be between 0 and 59.</param>
  71. /// <param name="milliseconds">An integer that represents a number
  72. /// of milliseconds, should be between 0 and 999999.</param>
  73. /// <exception cref="T:System.ArgumentOutOfRangeException">
  74. /// The Exception is thrown, if one of the parameter is outside the
  75. /// allowed the range.
  76. /// </exception>
  77. internal void M_CheckHMSM(int hour, int minute, int second,
  78. int milliseconds)
  79. {
  80. M_ArgumentInRange("hour", hour, 0, 23);
  81. M_ArgumentInRange("minute", minute, 0, 59);
  82. M_ArgumentInRange("second", second, 0, 59);
  83. M_ArgumentInRange("milliseconds", milliseconds, 0, 999999);
  84. }
  85. /// <value>
  86. /// A represantation of the CurrentEra.
  87. /// </value>
  88. public const int CurrentEra = 0;
  89. /// <value>When overridden gives the eras supported by the
  90. /// calendar as an array of integers.
  91. /// </value>
  92. public abstract int[] Eras { get; }
  93. /// <summary>
  94. /// The protected member stores the value for the
  95. /// <see cref="P:TwoDigitYearMax"/>
  96. /// property.
  97. /// </summary>
  98. internal int M_TwoDigitYearMax;
  99. /// <summary>
  100. /// Private field containing the maximum year for the calendar.
  101. /// </summary>
  102. private int M_MaxYearValue = 0;
  103. /// <value>
  104. /// Get-only property returing the maximum allowed year for this
  105. /// class.
  106. /// </value>
  107. internal virtual int M_MaxYear {
  108. get {
  109. if (M_MaxYearValue == 0) {
  110. M_MaxYearValue = GetYear(DateTime.MaxValue);
  111. }
  112. return M_MaxYearValue;
  113. }
  114. }
  115. /// <summary>
  116. /// Checks whether the year is the era is valid, if era = CurrentEra
  117. /// the right value is set.
  118. /// </summary>
  119. /// <param name="year">The year to check.</param>
  120. /// <param name="era">The era to check.</Param>
  121. /// <exception cref="T:ArgumentOutOfRangeException">
  122. /// The exception will be thrown, if the year is not valid.
  123. /// </exception>
  124. internal abstract void M_CheckYE(int year, ref int era);
  125. /// <value>
  126. /// <para>The property gives the maximum value for years with two
  127. /// digits. If the property has the value 2029, than the two-digit
  128. /// integer 29 results in the year 2029 and 30 in the
  129. /// year 1930.</para>
  130. /// <para>It might be overridden.</para>
  131. /// </value>
  132. public virtual int TwoDigitYearMax {
  133. get { return M_TwoDigitYearMax; }
  134. set {
  135. M_ArgumentInRange("year", value, 100, M_MaxYear);
  136. int era = CurrentEra;
  137. M_CheckYE(value, ref era);
  138. M_TwoDigitYearMax = value;
  139. }
  140. }
  141. /// <summary>
  142. /// The virtual method adds days to a given date.
  143. /// </summary>
  144. /// <param name="time">The
  145. /// <see cref="T:System.DateTime"/> to which to add
  146. /// days.
  147. /// </param>
  148. /// <param name="days">The number of days to add.</param>
  149. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  150. /// results from adding <paramref name="days"/> to the specified
  151. /// DateTime.</returns>
  152. public virtual DateTime AddDays(DateTime time, int days) {
  153. return time.Add(TimeSpan.FromDays(days));
  154. }
  155. /// <summary>
  156. /// The virtual method adds hours to a given date.
  157. /// </summary>
  158. /// <param name="time">The
  159. /// <see cref="T:System.DateTime"/> to which to add
  160. /// hours.
  161. /// </param>
  162. /// <param name="hours">The number of hours to add.</param>
  163. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  164. /// results from adding <paramref name="hours"/> to the specified
  165. /// DateTime.</returns>
  166. public virtual DateTime AddHours(DateTime time, int hours) {
  167. return time.Add(TimeSpan.FromHours(hours));
  168. }
  169. /// <summary>
  170. /// The virtual method adds milliseconds to a given date.
  171. /// </summary>
  172. /// <param name="time">The
  173. /// <see cref="T:System.DateTime"/> to which to add
  174. /// milliseconds.
  175. /// </param>
  176. /// <param name="milliseconds">The number of milliseconds given as
  177. /// double to add. Keep in mind the 100 nanosecond resolution of
  178. /// <see cref="T:System.DateTime"/>.
  179. /// </param>
  180. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  181. /// results from adding <paramref name="milliseconds"/> to the specified
  182. /// DateTime.</returns>
  183. public virtual DateTime AddMilliseconds(DateTime time,
  184. double milliseconds)
  185. {
  186. return time.Add(TimeSpan.FromMilliseconds(milliseconds));
  187. }
  188. /// <summary>
  189. /// The virtual method adds minutes to a given date.
  190. /// </summary>
  191. /// <param name="time">The
  192. /// <see cref="T:System.DateTime"/> to which to add
  193. /// minutes.
  194. /// </param>
  195. /// <param name="minutes">The number of minutes to add.</param>
  196. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  197. /// results from adding <paramref name="minutes"/> to the specified
  198. /// DateTime.</returns>
  199. public virtual DateTime AddMinutes(DateTime time, int minutes) {
  200. return time.Add(TimeSpan.FromMinutes(minutes));
  201. }
  202. /// <summary>
  203. /// When overrideden adds months to a given date.
  204. /// </summary>
  205. /// <param name="time">The
  206. /// <see cref="T:System.DateTime"/> to which to add
  207. /// months.
  208. /// </param>
  209. /// <param name="months">The number of months to add.</param>
  210. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  211. /// results from adding <paramref name="months"/> to the specified
  212. /// DateTime.</returns>
  213. public abstract DateTime AddMonths(DateTime time, int months);
  214. /// <summary>
  215. /// The virtual method adds seconds to a given date.
  216. /// </summary>
  217. /// <param name="time">The
  218. /// <see cref="T:System.DateTime"/> to which to add
  219. /// seconds.
  220. /// </param>
  221. /// <param name="seconds">The number of seconds to add.</param>
  222. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  223. /// results from adding <paramref name="seconds"/> to the specified
  224. /// DateTime.</returns>
  225. public virtual DateTime AddSeconds(DateTime time, int seconds) {
  226. return time.Add(TimeSpan.FromSeconds(seconds));
  227. }
  228. /// <summary>
  229. /// A wirtual method that adds weeks to a given date.
  230. /// </summary>
  231. /// <param name="time">The
  232. /// <see cref="T:System.DateTime"/> to which to add
  233. /// weeks.
  234. /// </param>
  235. /// <param name="weeks">The number of weeks to add.</param>
  236. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  237. /// results from adding <paramref name="weeks"/> to the specified
  238. /// DateTime.</returns>
  239. public virtual DateTime AddWeeks(DateTime time, int weeks) {
  240. return time.AddDays(weeks * M_DaysInWeek);
  241. }
  242. /// <summary>
  243. /// When overrideden adds years to a given date.
  244. /// </summary>
  245. /// <param name="time">The
  246. /// <see cref="T:System.DateTime"/> to which to add
  247. /// years.
  248. /// </param>
  249. /// <param name="years">The number of years to add.</param>
  250. /// <returns>A new <see cref="T:System.DateTime"/> value, that
  251. /// results from adding <paramref name="years"/> to the specified
  252. /// DateTime.</returns>
  253. public abstract DateTime AddYears(DateTime time, int years);
  254. /// <summary>
  255. /// When overriden gets the day of the month from
  256. /// <paramref name="time"/>.
  257. /// </summary>
  258. /// <param name="time">The
  259. /// <see cref="T:System.DateTime"/> that specifies a
  260. /// date.
  261. /// </param>
  262. /// <returns>An integer giving the day of months, starting with 1.
  263. /// </returns>
  264. public abstract int GetDayOfMonth(DateTime time);
  265. /// <summary>
  266. /// When overriden gets the day of the week from the specified date.
  267. /// </summary>
  268. /// <param name="time">The
  269. /// <see cref="T:System.DateTime"/> that specifies a
  270. /// date.
  271. /// </param>
  272. /// <returns>An integer giving the day of months, starting with 1.
  273. /// </returns>
  274. public abstract DayOfWeek GetDayOfWeek(DateTime time);
  275. /// <summary>
  276. /// When overridden gives the number of the day in the year.
  277. /// </summary>
  278. /// <param name="time">The
  279. /// <see cref="T:System.DateTime"/> that specifies a
  280. /// date.
  281. /// </param>
  282. /// <returns>An integer representing the day of the year,
  283. /// starting with 1.</returns>
  284. public abstract int GetDayOfYear(DateTime time);
  285. /// <summary>
  286. /// A virtual method that gives the number of days of the specified
  287. /// month of the <paramref name="year"/> and the
  288. /// <see cref="P:CurrentEra"/>.
  289. /// </summary>
  290. /// <param name="year">An integer that gives the year in the current
  291. /// era.</param>
  292. /// <param name="month">An integer that gives the month, starting
  293. /// with 1.</param>
  294. /// <returns>An integer that gives the number of days of the
  295. /// specified month.</returns>
  296. /// <exception cref="T:System.ArgumentOutOfRangeException">
  297. /// The exception is thrown, if <paramref name="month"/> or
  298. /// <paramref name="year"/> is outside the allowed range.
  299. /// </exception>
  300. public virtual int GetDaysInMonth(int year, int month) {
  301. return GetDaysInMonth(year, month, CurrentEra);
  302. }
  303. /// <summary>
  304. /// When overridden gives the number of days in the specified month
  305. /// of the given year and era.
  306. /// </summary>
  307. /// <param name="year">An integer that gives the year.
  308. /// </param>
  309. /// <param name="month">An integer that gives the month, starting
  310. /// with 1.</param>
  311. /// <param name="era">An intger that gives the era of the specified
  312. /// year.</param>
  313. /// <returns>An integer that gives the number of days of the
  314. /// specified month.</returns>
  315. /// <exception cref="T:System.ArgumentOutOfRangeException">
  316. /// The exception is thrown, if <paramref name="month"/>,
  317. /// <paramref name="year"/> ,or <paramref name="era"/> is outside
  318. /// the allowed range.
  319. /// </exception>
  320. public abstract int GetDaysInMonth(int year, int month, int era);
  321. /// <summary>
  322. /// A virtual method that gives the number of days of the specified
  323. /// year of the <see cref="P:CurrentEra"/>.
  324. /// </summary>
  325. /// <param name="year">An integer that gives the year in the current
  326. /// era.</param>
  327. /// <returns>An integer that gives the number of days of the
  328. /// specified year.</returns>
  329. /// <exception cref="T:System.ArgumentOutOfRangeException">
  330. /// The exception is thrown, if
  331. /// <paramref name="year"/> is outside the allowed range.
  332. /// </exception>
  333. public virtual int GetDaysInYear(int year) {
  334. return GetDaysInYear(year, CurrentEra);
  335. }
  336. /// <summary>
  337. /// When overridden gives the number of days of the specified
  338. /// year of the given era..
  339. /// </summary>
  340. /// <param name="year">An integer that specifies the year.
  341. /// </param>
  342. /// <param name="era">An ineger that specifies the era.
  343. /// </param>
  344. /// <returns>An integer that gives the number of days of the
  345. /// specified year.</returns>
  346. /// <exception cref="T:System.ArgumentOutOfRangeExceiption">
  347. /// The exception is thrown, if
  348. /// <paramref name="year"/> is outside the allowed range.
  349. /// </exception>
  350. public abstract int GetDaysInYear(int year, int era);
  351. /// <summary>
  352. /// When overridden gives the era of the specified date.
  353. /// </summary>
  354. /// <param name="time">The
  355. /// <see cref="T:System.DateTime"/> that specifies a
  356. /// date.
  357. /// </param>
  358. /// <returns>An integer representing the era of the calendar.
  359. /// </returns>
  360. public abstract int GetEra(DateTime time);
  361. /// <summary>
  362. /// Virtual method that gives the hour of the specified time.
  363. /// </summary>
  364. /// <param name="time">The
  365. /// <see cref="T:System.DateTime"/> that specifies the
  366. /// time.
  367. /// </param>
  368. /// <returns>An integer that gives the hour of the specified time,
  369. /// starting with 0.</returns>
  370. public virtual int GetHour(DateTime time) {
  371. return time.TimeOfDay.Hours;
  372. }
  373. /// <summary>
  374. /// Virtual method that gives the milliseconds in the current second
  375. /// of the specified time.
  376. /// </summary>
  377. /// <param name="time">The
  378. /// <see cref="T:System.DateTime"/> that specifies the
  379. /// time.
  380. /// </param>
  381. /// <returns>An integer that gives the milliseconds in the seconds
  382. /// of the specified time, starting with 0.</returns>
  383. public virtual double GetMilliseconds(DateTime time) {
  384. return time.TimeOfDay.Milliseconds;
  385. }
  386. /// <summary>
  387. /// Virtual method that gives the minute of the specified time.
  388. /// </summary>
  389. /// <param name="time">The
  390. /// <see cref="T:System.DateTime"/> that specifies the
  391. /// time.
  392. /// </param>
  393. /// <returns>An integer that gives the minute of the specified time,
  394. /// starting with 0.</returns>
  395. public virtual int GetMinute(DateTime time) {
  396. return time.TimeOfDay.Minutes;
  397. }
  398. /// <summary>
  399. /// When overridden gives the number of the month of the specified
  400. /// date.
  401. /// </summary>
  402. /// <param name="time">The
  403. /// <see cref="T:System.DateTime"/> that specifies a
  404. /// date.
  405. /// </param>
  406. /// <returns>An integer representing the month,
  407. /// starting with 1.</returns>
  408. public abstract int GetMonth(DateTime time);
  409. /// <summary>
  410. /// Virtual method that gives the number of months of the specified
  411. /// year of the <see cref="M:CurrentEra"/>.
  412. /// </summary>
  413. /// <param name="year">An integer that specifies the year in the
  414. /// current era.
  415. /// </param>
  416. /// <returns>An integer that gives the number of the months in the
  417. /// specified year.</returns>
  418. /// <exception cref="T:System.ArgumentOutOfRangeException">
  419. /// The exception is thrown, if the year is not allowed in the
  420. /// current era.
  421. /// </exception>
  422. public virtual int GetMonthsInYear(int year) {
  423. return GetMonthsInYear(year, CurrentEra);
  424. }
  425. /// <summary>
  426. /// When overridden gives the number of months in the specified year
  427. /// and era.
  428. /// </summary>
  429. /// <param name="year">An integer that specifies the year.
  430. /// </param>
  431. /// <param name="era">An integer that specifies the era.
  432. /// </param>
  433. /// <returns>An integer that gives the number of the months in the
  434. /// specified year.</returns>
  435. /// <exception cref="T:System.ArgumentOutOfRangeException">
  436. /// The exception is thrown, if the year or the era are not valid.
  437. /// </exception>
  438. public abstract int GetMonthsInYear(int year, int era);
  439. /// <summary>
  440. /// Virtual method that gives the second of the specified time.
  441. /// </summary>
  442. /// <param name="time">The
  443. /// <see cref="T:System.DateTime"/> that specifies the
  444. /// time.
  445. /// </param>
  446. /// <returns>An integer that gives the second of the specified time,
  447. /// starting with 0.</returns>
  448. public virtual int GetSecond(DateTime time) {
  449. return time.TimeOfDay.Seconds;
  450. }
  451. /// <summary>
  452. /// A protected method to calculate the number of days between two
  453. /// dates.
  454. /// </summary>
  455. /// <param name="timeA">A <see cref="T:System.DateTime"/>
  456. /// representing the first date.
  457. /// </param>
  458. /// <param name="timeB">A <see cref="T:System.DateTime"/>
  459. /// representing the second date.
  460. /// </param>
  461. /// <returns>An integer that represents the difference of days
  462. /// between <paramref name="timeA"/> and <paramref name="timeB"/>.
  463. /// </returns>
  464. internal int M_DiffDays(DateTime timeA, DateTime timeB) {
  465. long diff = timeA.Ticks - timeB.Ticks;
  466. if (diff >= 0) {
  467. return (int)(diff/TimeSpan.TicksPerDay);
  468. }
  469. diff += 1;
  470. return -1 + (int)(diff/TimeSpan.TicksPerDay);
  471. }
  472. /// <summary>
  473. /// A protected method that gives the first day of the second week of
  474. /// the year.
  475. /// </summary>
  476. /// <param name="year">An integer that represents the year.</param>
  477. /// <param name="rule">The
  478. /// <see cref="T:System.Globalization.CalendarWeekRule"/>
  479. /// to be used for the calculation.
  480. /// </param>
  481. /// <param name="firstDayOfWeek">
  482. /// The <see cref="T:System.Globalization.DayOfWeek"/>
  483. /// specifying the first day in a week.
  484. /// </param>
  485. /// <returns>The <see cref="T:System.DateTime"/> representing
  486. /// the first day of the second week of the year.
  487. /// </returns>
  488. internal DateTime M_GetFirstDayOfSecondWeekOfYear(
  489. int year, CalendarWeekRule rule, DayOfWeek firstDayOfWeek)
  490. {
  491. DateTime d1 = ToDateTime(year, 1, 1, 0, 0, 0, 0);
  492. int dow1 = (int)GetDayOfWeek(d1);
  493. int fdow = (int)firstDayOfWeek;
  494. int d = 0;
  495. switch (rule) {
  496. case CalendarWeekRule.FirstDay:
  497. if (fdow > dow1) {
  498. d += fdow - dow1;
  499. }
  500. else {
  501. d += fdow + M_DaysInWeek - dow1;
  502. }
  503. break;
  504. case CalendarWeekRule.FirstFullWeek:
  505. d = M_DaysInWeek;
  506. if (fdow >= dow1) {
  507. d += fdow - dow1;
  508. }
  509. else {
  510. d += fdow + M_DaysInWeek - dow1;
  511. }
  512. break;
  513. case CalendarWeekRule.FirstFourDayWeek:
  514. int dow4 = (dow1 + 3)%M_DaysInWeek;
  515. d = 3;
  516. if (fdow > dow4) {
  517. d += fdow - dow4;
  518. }
  519. else {
  520. d += fdow + M_DaysInWeek - dow4;
  521. }
  522. break;
  523. }
  524. return AddDays(d1, d);
  525. }
  526. /// <summary>
  527. /// A virtual method that gives the number of the week in the year.
  528. /// </summary>
  529. /// <param name="time">A
  530. /// <see cref="T:System.DateTime"/> representing the date.
  531. /// </param>
  532. /// <param name="rule">The
  533. /// <see cref="T:System.Globalization.CalendarWeekRule"/>
  534. /// to be used for the calculation.
  535. /// </param>
  536. /// <param name="firstDayOfWeek">
  537. /// The <see cref="T:System.Globalization.DayOfWeek"/>
  538. /// specifying the first day in a week.
  539. /// </param>
  540. /// <returns>An integer representing the number of the week in the
  541. /// year, starting with 1.
  542. /// </returns>
  543. public virtual int GetWeekOfYear(DateTime time,
  544. CalendarWeekRule rule,
  545. DayOfWeek firstDayOfWeek)
  546. {
  547. if (firstDayOfWeek < DayOfWeek.Sunday ||
  548. DayOfWeek.Saturday < firstDayOfWeek)
  549. {
  550. throw new ArgumentOutOfRangeException("firstDayOfWeek",
  551. "Value is not a valid day of week.");
  552. }
  553. int year = GetYear(time);
  554. int days;
  555. while (true) {
  556. DateTime secondWeek = M_GetFirstDayOfSecondWeekOfYear(
  557. year, rule, firstDayOfWeek);
  558. days = M_DiffDays(time, secondWeek) + M_DaysInWeek;
  559. if (days >= 0)
  560. break;
  561. year -= 1;
  562. }
  563. return 1 + days/M_DaysInWeek;
  564. }
  565. /// <summary>
  566. /// When overridden gives the number of the year of the specified
  567. /// date.
  568. /// </summary>
  569. /// <param name="time">The
  570. /// <see cref="T:System.DateTime"/> that specifies a
  571. /// date.
  572. /// </param>
  573. /// <returns>An integer representing the year,
  574. /// starting with 1.</returns>
  575. public abstract int GetYear(DateTime time);
  576. /// <summary>
  577. /// A virtual method that tells whether the given day in the
  578. /// <see cref="M:CurrentEra"/> is a leap day.
  579. /// </summary>
  580. /// <param name="year">An integer that specifies the year in the
  581. /// current era.
  582. /// </param>
  583. /// <param name="month">An integer that specifies the month.
  584. /// </param>
  585. /// <param name="day">An integer that specifies the day.
  586. /// </param>
  587. /// <returns>A boolean that tells whether the given day is a leap
  588. /// day.
  589. /// </returns>
  590. /// <exception cref="T:System.ArgumentOutOfRangeException">
  591. /// The exception is thrown, if the year, month or day is not valid
  592. /// the current era.
  593. /// </exception>
  594. public virtual bool IsLeapDay(int year, int month, int day) {
  595. return IsLeapDay(year, month, day, CurrentEra);
  596. }
  597. /// <summary>
  598. /// Tells when overridden whether the given day
  599. /// is a leap day.
  600. /// </summary>
  601. /// <param name="year">An integer that specifies the year in the
  602. /// given era.
  603. /// </param>
  604. /// <param name="month">An integer that specifies the month.
  605. /// </param>
  606. /// <param name="day">An integer that specifies the day.
  607. /// </param>
  608. /// <param name="era">An integer that specifies the era.
  609. /// </param>
  610. /// <returns>A boolean that tells whether the given day is a leap
  611. /// day.
  612. /// </returns>
  613. /// <exception cref="T:System.ArgumentOutOfRangeException">
  614. /// The exception is thrown, if the year, month, day, or era is not
  615. /// valid.
  616. /// </exception>
  617. public abstract bool IsLeapDay(int year, int month, int day, int era);
  618. /// <summary>
  619. /// A virtual method that tells whether the given month of the
  620. /// specified year in the
  621. /// <see cref="M:CurrentEra"/> is a leap month.
  622. /// </summary>
  623. /// <param name="year">An integer that specifies the year in the
  624. /// current era.
  625. /// </param>
  626. /// <param name="month">An integer that specifies the month.
  627. /// </param>
  628. /// <returns>A boolean that tells whether the given month is a leap
  629. /// month.
  630. /// </returns>
  631. /// <exception cref="T:System.ArgumentOutOfRangeException">
  632. /// The exception is thrown, if the year or month is not valid
  633. /// the current era.
  634. /// </exception>
  635. public virtual bool IsLeapMonth(int year, int month) {
  636. return IsLeapMonth(year, month, CurrentEra);
  637. }
  638. /// <summary>
  639. /// Tells when overridden whether the given month
  640. /// is a leap month.
  641. /// </summary>
  642. /// <param name="year">An integer that specifies the year in the
  643. /// given era.
  644. /// </param>
  645. /// <param name="month">An integer that specifies the month.
  646. /// </param>
  647. /// <param name="era">An integer that specifies the era.
  648. /// </param>
  649. /// <returns>A boolean that tells whether the given month is a leap
  650. /// month.
  651. /// </returns>
  652. /// <exception cref="T:System.ArgumentOutOfRangeException">
  653. /// The exception is thrown, if the year, month, or era is not
  654. /// valid.
  655. /// </exception>
  656. public abstract bool IsLeapMonth(int year, int month, int era);
  657. /// <summary>
  658. /// A virtual method that tells whether the given year
  659. /// in the
  660. /// <see cref="M:CurrentEra"/> is a leap year.
  661. /// </summary>
  662. /// <param name="year">An integer that specifies the year in the
  663. /// current era.
  664. /// </param>
  665. /// <returns>A boolean that tells whether the given year is a leap
  666. /// year.
  667. /// </returns>
  668. /// <exception cref="T:System.ArgumentOutOfRangeException">
  669. /// The exception is thrown, if the year is not valid
  670. /// the current era.
  671. /// </exception>
  672. public virtual bool IsLeapYear(int year) {
  673. return IsLeapYear(year, CurrentEra);
  674. }
  675. /// <summary>
  676. /// Tells when overridden whether the given year
  677. /// is a leap year.
  678. /// </summary>
  679. /// <param name="year">An integer that specifies the year in the
  680. /// given era.
  681. /// </param>
  682. /// <param name="era">An integer that specifies the era.
  683. /// </param>
  684. /// <returns>A boolean that tells whether the given year is a leap
  685. /// year.
  686. /// </returns>
  687. /// <exception cref="T:System.ArgumentOutOfRangeException">
  688. /// The exception is thrown, if the year or era is not
  689. /// valid.
  690. /// </exception>
  691. public abstract bool IsLeapYear(int year, int era);
  692. /// <summary>
  693. /// A virtual method that creates the
  694. /// <see cref="T:System.DateTime"/> from the parameters.
  695. /// </summary>
  696. /// <param name="year">An integer that gives the year in the
  697. /// <see cref="M:CurrentEra"/>.
  698. /// </param>
  699. /// <param name="month">An integer that specifies the month.
  700. /// </param>
  701. /// <param name="day">An integer that specifies the day.
  702. /// </param>
  703. /// <param name="hour">An integer that specifies the hour.
  704. /// </param>
  705. /// <param name="minute">An integer that specifies the minute.
  706. /// </param>
  707. /// <param name="second">An integer that gives the second.
  708. /// </param>
  709. /// <param name="milliseconds">An integer that gives the
  710. /// milliseconds.
  711. /// </param>
  712. /// <returns>A
  713. /// <see cref="T:system.DateTime"/> representig the date and time.
  714. /// </returns>
  715. /// <exception cref="T:System.ArgumentOutOfRangeException">
  716. /// The exception is thrown, if at least one of the parameters
  717. /// is out of range.
  718. /// </exception>
  719. public virtual DateTime ToDateTime(int year, int month, int day,
  720. int hour, int minute, int second, int milliseconds)
  721. {
  722. return ToDateTime(year, month, day, hour, minute, second,
  723. milliseconds, CurrentEra);
  724. }
  725. /// <summary>
  726. /// When overridden creates the
  727. /// <see cref="T:System.DateTime"/> from the parameters.
  728. /// </summary>
  729. /// <param name="year">An integer that gives the year in the
  730. /// <paramref name="era"/>.
  731. /// </param>
  732. /// <param name="month">An integer that specifies the month.
  733. /// </param>
  734. /// <param name="day">An integer that specifies the day.
  735. /// </param>
  736. /// <param name="hour">An integer that specifies the hour.
  737. /// </param>
  738. /// <param name="minute">An integer that specifies the minute.
  739. /// </param>
  740. /// <param name="second">An integer that gives the second.
  741. /// </param>
  742. /// <param name="milliseconds">An integer that gives the
  743. /// milliseconds.
  744. /// </param>
  745. /// <param name="era">An integer that specifies the era.
  746. /// </param>
  747. /// <returns>A
  748. /// <see cref="T:system.DateTime"/> representig the date and time.
  749. /// </returns>
  750. /// <exception cref="T:System.ArgumentOutOfRangeException">
  751. /// The exception is thrown, if at least one of the parameters
  752. /// is out of range.
  753. /// </exception>
  754. public abstract DateTime ToDateTime(int year, int month, int day,
  755. int hour, int minute, int second, int milliseconds,
  756. int era);
  757. /// <summary>
  758. /// A virtual method that converts a two-digit year to a four-digit
  759. /// year. It uses the <see cref="M:TwoDigitYearMax"/> property.
  760. /// </summary>
  761. /// <param name="year">An integer that gives the two-digit year.
  762. /// </param>
  763. /// <returns>An integer giving the four digit year.
  764. /// </returns>
  765. /// <exception cref="T:System.ArgumentOutOfRangeException">
  766. /// The exception is thrown if the year is negative or the resulting
  767. /// year is invalid.
  768. /// </exception>
  769. public virtual int ToFourDigitYear(int year) {
  770. if (year < 0)
  771. throw new ArgumentOutOfRangeException(
  772. "year", "Non-negative number required.");
  773. /* seems not to be the right thing to do, but .NET is
  774. * doing it this way.
  775. */
  776. if (year <= 99) {
  777. int year2 = TwoDigitYearMax%100;
  778. int d = year - year2;
  779. year = TwoDigitYearMax + d + (d <= 0 ? 0 : -100);
  780. }
  781. int era = CurrentEra;
  782. M_CheckYE(year, ref era);
  783. return year;
  784. }
  785. // TwoDigitYearMax: Windows reads it from the Registry, we
  786. // should have an XML file with the defaults
  787. /// <summary>
  788. /// The default constructor, is sets the TwoDigitYearMax to 2029.
  789. /// </summary>
  790. /// <remarks>
  791. /// The .NET framework reads the value from the registry.
  792. /// We should implement it here. Currently I set the default values
  793. /// in the ctors of the derived classes, if it is 99.
  794. /// </remarks>
  795. protected Calendar() {
  796. M_TwoDigitYearMax = 99;
  797. }
  798. /// <summary>Protected field storing the abbreviated era names.
  799. /// </summary>
  800. internal string[] M_AbbrEraNames;
  801. /// <summary>Protected field storing the era names.
  802. /// </summary>
  803. internal string[] M_EraNames;
  804. /// <value>
  805. /// The property stores the era names. It might be overwritten by
  806. /// CultureInfo.
  807. /// </value>
  808. internal string[] AbbreviatedEraNames {
  809. get {
  810. if (M_AbbrEraNames == null ||
  811. M_AbbrEraNames.Length != Eras.Length)
  812. throw new Exception(
  813. "Internal: M_AbbrEraNames " +
  814. "wrong initialized!");
  815. return (string[])M_AbbrEraNames.Clone();
  816. }
  817. set {
  818. if (value.Length != Eras.Length) {
  819. StringWriter sw = new StringWriter();
  820. sw.Write("Array length must be equal Eras " +
  821. "length {0}.", Eras.Length);
  822. throw new ArgumentException(
  823. sw.ToString());
  824. }
  825. M_AbbrEraNames = (string[])value.Clone();
  826. }
  827. }
  828. /// <value>
  829. /// The property stores the era names. It might be overwritten by
  830. /// CultureInfo.
  831. /// </value>
  832. internal string[] EraNames {
  833. get {
  834. if (M_EraNames == null ||
  835. M_EraNames.Length != Eras.Length)
  836. throw new Exception(
  837. "Internal: M_EraNames " +
  838. "not initialized!");
  839. return (string[])M_EraNames.Clone();
  840. }
  841. set {
  842. if (value.Length != Eras.Length) {
  843. StringWriter sw = new StringWriter();
  844. sw.Write("Array length must be equal Eras " +
  845. "length {0}.", Eras.Length);
  846. throw new ArgumentException(
  847. sw.ToString());
  848. }
  849. M_EraNames = (string[])value.Clone();
  850. }
  851. }
  852. } // class Calendar
  853. } // namespace System.Globalization