Calendar.cs 30 KB

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