PageRenderTime 61ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/Attic/MvpXmlLibrary/EXSLT/v1/src/Exslt/ExsltDatesAndTimes.cs

#
C# | 2360 lines | 1539 code | 211 blank | 610 comment | 168 complexity | 8491770fd6f8167d74a98ecdb3d5fe3e MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #region using
  2. using System;
  3. using System.Globalization;
  4. using System.Xml;
  5. using System.Xml.XPath;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. #endregion
  9. namespace Mvp.Xml.Exslt
  10. {
  11. /// <summary>
  12. /// This class implements the EXSLT functions in the http://exslt.org/dates-and-times namespace.
  13. /// </summary>
  14. public class ExsltDatesAndTimes
  15. {
  16. private CultureInfo ci = new CultureInfo("en-US");
  17. private class ExsltDateTimeFactory
  18. {
  19. /// <summary>
  20. /// Parse a date and time for format-date()
  21. /// </summary>
  22. /// <param name="d"></param>
  23. /// <returns></returns>
  24. public static ExsltDateTime ParseDateTime(string d)
  25. {
  26. // First try any of the classes in ParseDate
  27. try
  28. {
  29. return ParseDate(d);
  30. }
  31. catch(FormatException)
  32. {
  33. }
  34. try
  35. {
  36. TimeTZ t = new TimeTZ(d);
  37. return t;
  38. }
  39. catch(FormatException)
  40. {
  41. }
  42. try
  43. {
  44. MonthDay t = new MonthDay(d);
  45. return t;
  46. }
  47. catch(FormatException)
  48. {
  49. }
  50. try
  51. {
  52. Month t = new Month(d);
  53. return t;
  54. }
  55. catch(FormatException)
  56. {
  57. }
  58. // Finally day -- don't catch the exception
  59. {
  60. Day t = new Day(d);
  61. return t;
  62. }
  63. }
  64. /// <summary>
  65. /// Initialize the structure with the current date, time and timezone
  66. /// </summary>
  67. public static ExsltDateTime ParseDate(string d)
  68. {
  69. // Try each potential class, from most specific to least specific.
  70. // First DateTimeTZ
  71. try
  72. {
  73. DateTimeTZ t = new DateTimeTZ(d);
  74. return t;
  75. }
  76. catch(FormatException)
  77. {
  78. }
  79. // Next Date
  80. try
  81. {
  82. DateTZ t = new DateTZ(d);
  83. return t;
  84. }
  85. catch(FormatException)
  86. {
  87. }
  88. // Next YearMonth
  89. try
  90. {
  91. YearMonth t = new YearMonth(d);
  92. return t;
  93. }
  94. catch(FormatException)
  95. {
  96. }
  97. // Finally Year -- don't catch the exception for the last type
  98. {
  99. YearTZ t = new YearTZ(d);
  100. return t;
  101. }
  102. }
  103. }
  104. internal abstract class ExsltDateTime
  105. {
  106. public DateTime d;
  107. public TimeSpan ts = new TimeSpan(TimeSpan.MinValue.Ticks);
  108. protected CultureInfo ci = new CultureInfo("en-US");
  109. /// <summary>
  110. /// Initialize the structure with the current date, time and timezone
  111. /// </summary>
  112. public ExsltDateTime()
  113. {
  114. d = DateTime.Now;
  115. TimeZone tz = TimeZone.CurrentTimeZone;
  116. ts = tz.GetUtcOffset(d);
  117. }
  118. /// <summary>
  119. /// Initialize the DateTimeTZ structure with the date, time and timezone in the string.
  120. /// </summary>
  121. /// <param name="inS">An ISO8601 string</param>
  122. public ExsltDateTime(string inS)
  123. {
  124. String s = inS.Trim();
  125. d = DateTime.ParseExact(s, expectedFormats, ci, DateTimeStyles.AdjustToUniversal);
  126. if (s.EndsWith("Z"))
  127. ts = new TimeSpan(0, 0, 0);
  128. else if (s.Length > 6)
  129. {
  130. String zoneStr = s.Substring(s.Length-6, 6);
  131. if (zoneStr[3] == ':')
  132. {
  133. try
  134. {
  135. int hours = Int32.Parse(zoneStr.Substring(0,3));
  136. int minutes = Int32.Parse(zoneStr.Substring(4,2));
  137. if (hours < 0)
  138. minutes = -minutes;
  139. ts = new TimeSpan(hours, minutes, 0);
  140. d = d.Add(ts); // Adjust to time zone relative time
  141. }
  142. catch(Exception)
  143. {
  144. }
  145. }
  146. }
  147. }
  148. /// <summary>
  149. /// Exslt Copy constructor
  150. /// Initialize the structure with the date, time and timezone in the string.
  151. /// </summary>
  152. /// <param name="inS">An ExsltDateTime</param>
  153. public ExsltDateTime(ExsltDateTime inS)
  154. {
  155. d = inS.d;
  156. ts = inS.ts;
  157. }
  158. public bool HasTimeZone()
  159. {
  160. return !(TimeSpan.MinValue.Ticks == ts.Ticks);
  161. }
  162. public DateTime ToUniversalTime()
  163. {
  164. if (!HasTimeZone())
  165. return d;
  166. else
  167. return d.Subtract(ts);
  168. }
  169. /// <summary>
  170. /// Output as a standard (ISO8601) string
  171. /// </summary>
  172. /// <returns>the date and time as an ISO8601 string. includes timezone</returns>
  173. public override string ToString()
  174. {
  175. return this.ToString(outputFormat);
  176. }
  177. /// <summary>
  178. /// Output as a formatted string
  179. /// </summary>
  180. /// <returns>the date and time as a formatted string. includes timezone</returns>
  181. public string ToString(String of)
  182. {
  183. StringBuilder retString = new StringBuilder("");
  184. retString.Append(d.ToString(of));
  185. retString.Append(GetTimeZone());
  186. return retString.ToString();
  187. }
  188. public string GetTimeZone()
  189. {
  190. StringBuilder retString = new StringBuilder();
  191. // if no ts specified, output without ts
  192. if (HasTimeZone())
  193. {
  194. if (0 == ts.Hours && 0 == ts.Minutes)
  195. retString.Append('Z');
  196. else if (ts.Hours >= 0 && ts.Minutes >= 0)
  197. {
  198. retString.Append('+');
  199. retString.Append(ts.Hours.ToString().PadLeft(2, '0'));
  200. retString.Append(':');
  201. retString.Append(ts.Minutes.ToString().PadLeft(2, '0'));
  202. }
  203. else
  204. {
  205. retString.Append('-');
  206. retString.Append((-ts.Hours).ToString().PadLeft(2, '0'));
  207. retString.Append(':');
  208. retString.Append((-ts.Minutes).ToString().PadLeft(2, '0'));
  209. }
  210. }
  211. return retString.ToString();
  212. }
  213. public string GetGMTOffsetTimeZone()
  214. {
  215. StringBuilder retString = new StringBuilder();
  216. // if no ts specified, output without ts
  217. if (HasTimeZone())
  218. {
  219. retString.Append("GMT");
  220. if (0 != ts.Hours || 0 != ts.Minutes)
  221. {
  222. retString.Append(GetTimeZone());
  223. }
  224. }
  225. return retString.ToString();
  226. }
  227. public string Get822TimeZone()
  228. {
  229. StringBuilder retString = new StringBuilder();
  230. // if no ts specified, output without ts
  231. if (HasTimeZone())
  232. {
  233. if (0 == ts.Hours && 0 == ts.Minutes)
  234. retString.Append("GMT");
  235. else if (ts.Hours >= 0 && ts.Minutes >= 0)
  236. {
  237. retString.Append('+');
  238. retString.Append(ts.Hours.ToString().PadLeft(2, '0'));
  239. retString.Append(ts.Minutes.ToString().PadLeft(2, '0'));
  240. }
  241. else
  242. {
  243. retString.Append('-');
  244. retString.Append((-ts.Hours).ToString().PadLeft(2, '0'));
  245. retString.Append((-ts.Minutes).ToString().PadLeft(2, '0'));
  246. }
  247. }
  248. return retString.ToString();
  249. }
  250. protected abstract string[] expectedFormats {get;}
  251. protected abstract string outputFormat {get;}
  252. }
  253. internal class DateTimeTZ : ExsltDateTime
  254. {
  255. public DateTimeTZ() : base(){}
  256. public DateTimeTZ(string inS) : base(inS){}
  257. public DateTimeTZ(ExsltDateTime inS) : base(inS){}
  258. protected override string[] expectedFormats
  259. {
  260. get
  261. {
  262. return new string[] {"yyyy-MM-dd\"T\"HH:mm:sszzz",
  263. "yyyy-MM-dd\"T\"HH:mm:ssZ",
  264. "yyyy-MM-dd\"T\"HH:mm:ss",
  265. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffzzz",
  266. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffZ",
  267. "yyyy-MM-dd\"T\"HH:mm:ss.fffffff",
  268. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffzzz",
  269. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffZ",
  270. "yyyy-MM-dd\"T\"HH:mm:ss.ffffff",
  271. "yyyy-MM-dd\"T\"HH:mm:ss.fffffzzz",
  272. "yyyy-MM-dd\"T\"HH:mm:ss.fffffZ",
  273. "yyyy-MM-dd\"T\"HH:mm:ss.fffff",
  274. "yyyy-MM-dd\"T\"HH:mm:ss.ffffzzz",
  275. "yyyy-MM-dd\"T\"HH:mm:ss.ffffZ",
  276. "yyyy-MM-dd\"T\"HH:mm:ss.ffff",
  277. "yyyy-MM-dd\"T\"HH:mm:ss.fffzzz",
  278. "yyyy-MM-dd\"T\"HH:mm:ss.fffZ",
  279. "yyyy-MM-dd\"T\"HH:mm:ss.fff",
  280. "yyyy-MM-dd\"T\"HH:mm:ss.ffzzz",
  281. "yyyy-MM-dd\"T\"HH:mm:ss.ffZ",
  282. "yyyy-MM-dd\"T\"HH:mm:ss.ff",
  283. "yyyy-MM-dd\"T\"HH:mm:ss.fzzz",
  284. "yyyy-MM-dd\"T\"HH:mm:ss.fZ",
  285. "yyyy-MM-dd\"T\"HH:mm:ss.f"
  286. };
  287. }
  288. }
  289. protected override string outputFormat
  290. {
  291. get
  292. {
  293. return "yyyy-MM-dd\"T\"HH:mm:ss";
  294. }
  295. }
  296. }
  297. internal class DateTZ : ExsltDateTime
  298. {
  299. public DateTZ() : base(){}
  300. public DateTZ(string inS) : base(inS){}
  301. public DateTZ(ExsltDateTime inS) : base(inS){}
  302. protected override string[] expectedFormats
  303. {
  304. get
  305. {
  306. return new string[] {"yyyy-MM-dd\"T\"HH:mm:sszzz",
  307. "yyyy-MM-dd\"T\"HH:mm:ssZ",
  308. "yyyy-MM-dd\"T\"HH:mm:ss",
  309. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffzzz",
  310. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffZ",
  311. "yyyy-MM-dd\"T\"HH:mm:ss.fffffff",
  312. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffzzz",
  313. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffZ",
  314. "yyyy-MM-dd\"T\"HH:mm:ss.ffffff",
  315. "yyyy-MM-dd\"T\"HH:mm:ss.fffffzzz",
  316. "yyyy-MM-dd\"T\"HH:mm:ss.fffffZ",
  317. "yyyy-MM-dd\"T\"HH:mm:ss.fffff",
  318. "yyyy-MM-dd\"T\"HH:mm:ss.ffffzzz",
  319. "yyyy-MM-dd\"T\"HH:mm:ss.ffffZ",
  320. "yyyy-MM-dd\"T\"HH:mm:ss.ffff",
  321. "yyyy-MM-dd\"T\"HH:mm:ss.fffzzz",
  322. "yyyy-MM-dd\"T\"HH:mm:ss.fffZ",
  323. "yyyy-MM-dd\"T\"HH:mm:ss.fff",
  324. "yyyy-MM-dd\"T\"HH:mm:ss.ffzzz",
  325. "yyyy-MM-dd\"T\"HH:mm:ss.ffZ",
  326. "yyyy-MM-dd\"T\"HH:mm:ss.ff",
  327. "yyyy-MM-dd\"T\"HH:mm:ss.fzzz",
  328. "yyyy-MM-dd\"T\"HH:mm:ss.fZ",
  329. "yyyy-MM-dd\"T\"HH:mm:ss.f",
  330. "yyyy-MM-ddzzz",
  331. "yyyy-MM-ddZ",
  332. "yyyy-MM-dd"};
  333. }
  334. }
  335. protected override string outputFormat
  336. {
  337. get
  338. {
  339. return "yyyy-MM-dd";
  340. }
  341. }
  342. }
  343. internal class TimeTZ : ExsltDateTime
  344. {
  345. public TimeTZ(string inS) : base(inS){}
  346. public TimeTZ() : base(){}
  347. protected override string[] expectedFormats
  348. {
  349. get
  350. {
  351. return new string[] {"yyyy-MM-dd\"T\"HH:mm:sszzz",
  352. "yyyy-MM-dd\"T\"HH:mm:ssZ",
  353. "yyyy-MM-dd\"T\"HH:mm:ss",
  354. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffzzz",
  355. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffZ",
  356. "yyyy-MM-dd\"T\"HH:mm:ss.fffffff",
  357. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffzzz",
  358. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffZ",
  359. "yyyy-MM-dd\"T\"HH:mm:ss.ffffff",
  360. "yyyy-MM-dd\"T\"HH:mm:ss.fffffzzz",
  361. "yyyy-MM-dd\"T\"HH:mm:ss.fffffZ",
  362. "yyyy-MM-dd\"T\"HH:mm:ss.fffff",
  363. "yyyy-MM-dd\"T\"HH:mm:ss.ffffzzz",
  364. "yyyy-MM-dd\"T\"HH:mm:ss.ffffZ",
  365. "yyyy-MM-dd\"T\"HH:mm:ss.ffff",
  366. "yyyy-MM-dd\"T\"HH:mm:ss.fffzzz",
  367. "yyyy-MM-dd\"T\"HH:mm:ss.fffZ",
  368. "yyyy-MM-dd\"T\"HH:mm:ss.fff",
  369. "yyyy-MM-dd\"T\"HH:mm:ss.ffzzz",
  370. "yyyy-MM-dd\"T\"HH:mm:ss.ffZ",
  371. "yyyy-MM-dd\"T\"HH:mm:ss.ff",
  372. "yyyy-MM-dd\"T\"HH:mm:ss.fzzz",
  373. "yyyy-MM-dd\"T\"HH:mm:ss.fZ",
  374. "yyyy-MM-dd\"T\"HH:mm:ss.f",
  375. "HH:mm:sszzz",
  376. "HH:mm:ssZ",
  377. "HH:mm:ss"};
  378. }
  379. }
  380. protected override string outputFormat
  381. {
  382. get
  383. {
  384. return "HH:mm:ss";
  385. }
  386. }
  387. }
  388. internal class YearMonth : ExsltDateTime
  389. {
  390. public YearMonth() : base(){}
  391. public YearMonth(string inS) : base(inS){}
  392. public YearMonth(ExsltDateTime inS) : base(inS){}
  393. protected override string[] expectedFormats
  394. {
  395. get
  396. {
  397. return new string[] {"yyyy-MM-dd\"T\"HH:mm:sszzz",
  398. "yyyy-MM-dd\"T\"HH:mm:ssZ",
  399. "yyyy-MM-dd\"T\"HH:mm:ss",
  400. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffzzz",
  401. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffZ",
  402. "yyyy-MM-dd\"T\"HH:mm:ss.fffffff",
  403. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffzzz",
  404. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffZ",
  405. "yyyy-MM-dd\"T\"HH:mm:ss.ffffff",
  406. "yyyy-MM-dd\"T\"HH:mm:ss.fffffzzz",
  407. "yyyy-MM-dd\"T\"HH:mm:ss.fffffZ",
  408. "yyyy-MM-dd\"T\"HH:mm:ss.fffff",
  409. "yyyy-MM-dd\"T\"HH:mm:ss.ffffzzz",
  410. "yyyy-MM-dd\"T\"HH:mm:ss.ffffZ",
  411. "yyyy-MM-dd\"T\"HH:mm:ss.ffff",
  412. "yyyy-MM-dd\"T\"HH:mm:ss.fffzzz",
  413. "yyyy-MM-dd\"T\"HH:mm:ss.fffZ",
  414. "yyyy-MM-dd\"T\"HH:mm:ss.fff",
  415. "yyyy-MM-dd\"T\"HH:mm:ss.ffzzz",
  416. "yyyy-MM-dd\"T\"HH:mm:ss.ffZ",
  417. "yyyy-MM-dd\"T\"HH:mm:ss.ff",
  418. "yyyy-MM-dd\"T\"HH:mm:ss.fzzz",
  419. "yyyy-MM-dd\"T\"HH:mm:ss.fZ",
  420. "yyyy-MM-dd\"T\"HH:mm:ss.f",
  421. "yyyy-MM-dd",
  422. "yyyy-MM"};
  423. }
  424. }
  425. protected override string outputFormat
  426. {
  427. get
  428. {
  429. return "yyyy-MM";
  430. }
  431. }
  432. }
  433. internal class YearTZ : ExsltDateTime
  434. {
  435. public YearTZ() : base(){}
  436. public YearTZ(string inS) : base(inS){}
  437. public YearTZ(ExsltDateTime inS) : base(inS){}
  438. protected override string[] expectedFormats
  439. {
  440. get
  441. {
  442. return new string[] {"yyyy-MM-dd\"T\"HH:mm:sszzz",
  443. "yyyy-MM-dd\"T\"HH:mm:ssZ",
  444. "yyyy-MM-dd\"T\"HH:mm:ss",
  445. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffzzz",
  446. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffZ",
  447. "yyyy-MM-dd\"T\"HH:mm:ss.fffffff",
  448. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffzzz",
  449. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffZ",
  450. "yyyy-MM-dd\"T\"HH:mm:ss.ffffff",
  451. "yyyy-MM-dd\"T\"HH:mm:ss.fffffzzz",
  452. "yyyy-MM-dd\"T\"HH:mm:ss.fffffZ",
  453. "yyyy-MM-dd\"T\"HH:mm:ss.fffff",
  454. "yyyy-MM-dd\"T\"HH:mm:ss.ffffzzz",
  455. "yyyy-MM-dd\"T\"HH:mm:ss.ffffZ",
  456. "yyyy-MM-dd\"T\"HH:mm:ss.ffff",
  457. "yyyy-MM-dd\"T\"HH:mm:ss.fffzzz",
  458. "yyyy-MM-dd\"T\"HH:mm:ss.fffZ",
  459. "yyyy-MM-dd\"T\"HH:mm:ss.fff",
  460. "yyyy-MM-dd\"T\"HH:mm:ss.ffzzz",
  461. "yyyy-MM-dd\"T\"HH:mm:ss.ffZ",
  462. "yyyy-MM-dd\"T\"HH:mm:ss.ff",
  463. "yyyy-MM-dd\"T\"HH:mm:ss.fzzz",
  464. "yyyy-MM-dd\"T\"HH:mm:ss.fZ",
  465. "yyyy-MM-dd\"T\"HH:mm:ss.f",
  466. "yyyy-MM-dd",
  467. "yyyy-MM",
  468. "yyyy"};
  469. }
  470. }
  471. protected override string outputFormat
  472. {
  473. get
  474. {
  475. return "yyyy";
  476. }
  477. }
  478. }
  479. internal class Month : ExsltDateTime
  480. {
  481. public Month() : base(){}
  482. public Month(string inS) : base(inS){}
  483. public Month(ExsltDateTime inS) : base(inS){}
  484. protected override string[] expectedFormats
  485. {
  486. get
  487. {
  488. return new string[] {"yyyy-MM-dd\"T\"HH:mm:sszzz",
  489. "yyyy-MM-dd\"T\"HH:mm:ssZ",
  490. "yyyy-MM-dd\"T\"HH:mm:ss",
  491. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffzzz",
  492. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffZ",
  493. "yyyy-MM-dd\"T\"HH:mm:ss.fffffff",
  494. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffzzz",
  495. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffZ",
  496. "yyyy-MM-dd\"T\"HH:mm:ss.ffffff",
  497. "yyyy-MM-dd\"T\"HH:mm:ss.fffffzzz",
  498. "yyyy-MM-dd\"T\"HH:mm:ss.fffffZ",
  499. "yyyy-MM-dd\"T\"HH:mm:ss.fffff",
  500. "yyyy-MM-dd\"T\"HH:mm:ss.ffffzzz",
  501. "yyyy-MM-dd\"T\"HH:mm:ss.ffffZ",
  502. "yyyy-MM-dd\"T\"HH:mm:ss.ffff",
  503. "yyyy-MM-dd\"T\"HH:mm:ss.fffzzz",
  504. "yyyy-MM-dd\"T\"HH:mm:ss.fffZ",
  505. "yyyy-MM-dd\"T\"HH:mm:ss.fff",
  506. "yyyy-MM-dd\"T\"HH:mm:ss.ffzzz",
  507. "yyyy-MM-dd\"T\"HH:mm:ss.ffZ",
  508. "yyyy-MM-dd\"T\"HH:mm:ss.ff",
  509. "yyyy-MM-dd\"T\"HH:mm:ss.fzzz",
  510. "yyyy-MM-dd\"T\"HH:mm:ss.fZ",
  511. "yyyy-MM-dd\"T\"HH:mm:ss.f",
  512. "yyyy-MM-dd",
  513. "yyyy-MM",
  514. "--MM--"};
  515. }
  516. }
  517. protected override string outputFormat
  518. {
  519. get
  520. {
  521. return "--MM--";
  522. }
  523. }
  524. }
  525. internal class Day : ExsltDateTime
  526. {
  527. public Day() : base(){}
  528. public Day(string inS) : base(inS){}
  529. public Day(ExsltDateTime inS) : base(inS){}
  530. protected override string[] expectedFormats
  531. {
  532. get
  533. {
  534. return new string[] {"yyyy-MM-dd\"T\"HH:mm:sszzz",
  535. "yyyy-MM-dd\"T\"HH:mm:ssZ",
  536. "yyyy-MM-dd\"T\"HH:mm:ss",
  537. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffzzz",
  538. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffZ",
  539. "yyyy-MM-dd\"T\"HH:mm:ss.fffffff",
  540. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffzzz",
  541. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffZ",
  542. "yyyy-MM-dd\"T\"HH:mm:ss.ffffff",
  543. "yyyy-MM-dd\"T\"HH:mm:ss.fffffzzz",
  544. "yyyy-MM-dd\"T\"HH:mm:ss.fffffZ",
  545. "yyyy-MM-dd\"T\"HH:mm:ss.fffff",
  546. "yyyy-MM-dd\"T\"HH:mm:ss.ffffzzz",
  547. "yyyy-MM-dd\"T\"HH:mm:ss.ffffZ",
  548. "yyyy-MM-dd\"T\"HH:mm:ss.ffff",
  549. "yyyy-MM-dd\"T\"HH:mm:ss.fffzzz",
  550. "yyyy-MM-dd\"T\"HH:mm:ss.fffZ",
  551. "yyyy-MM-dd\"T\"HH:mm:ss.fff",
  552. "yyyy-MM-dd\"T\"HH:mm:ss.ffzzz",
  553. "yyyy-MM-dd\"T\"HH:mm:ss.ffZ",
  554. "yyyy-MM-dd\"T\"HH:mm:ss.ff",
  555. "yyyy-MM-dd\"T\"HH:mm:ss.fzzz",
  556. "yyyy-MM-dd\"T\"HH:mm:ss.fZ",
  557. "yyyy-MM-dd\"T\"HH:mm:ss.f",
  558. "yyyy-MM-dd",
  559. "---dd",
  560. "--MM-dd"};
  561. }
  562. }
  563. protected override string outputFormat
  564. {
  565. get
  566. {
  567. return "---dd";
  568. }
  569. }
  570. }
  571. internal class MonthDay : ExsltDateTime
  572. {
  573. public MonthDay() : base(){}
  574. public MonthDay(string inS) : base(inS){}
  575. public MonthDay(ExsltDateTime inS) : base(inS){}
  576. protected override string[] expectedFormats
  577. {
  578. get
  579. {
  580. return new string[] {"yyyy-MM-dd\"T\"HH:mm:sszzz",
  581. "yyyy-MM-dd\"T\"HH:mm:ssZ",
  582. "yyyy-MM-dd\"T\"HH:mm:ss",
  583. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffzzz",
  584. "yyyy-MM-dd\"T\"HH:mm:ss.fffffffZ",
  585. "yyyy-MM-dd\"T\"HH:mm:ss.fffffff",
  586. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffzzz",
  587. "yyyy-MM-dd\"T\"HH:mm:ss.ffffffZ",
  588. "yyyy-MM-dd\"T\"HH:mm:ss.ffffff",
  589. "yyyy-MM-dd\"T\"HH:mm:ss.fffffzzz",
  590. "yyyy-MM-dd\"T\"HH:mm:ss.fffffZ",
  591. "yyyy-MM-dd\"T\"HH:mm:ss.fffff",
  592. "yyyy-MM-dd\"T\"HH:mm:ss.ffffzzz",
  593. "yyyy-MM-dd\"T\"HH:mm:ss.ffffZ",
  594. "yyyy-MM-dd\"T\"HH:mm:ss.ffff",
  595. "yyyy-MM-dd\"T\"HH:mm:ss.fffzzz",
  596. "yyyy-MM-dd\"T\"HH:mm:ss.fffZ",
  597. "yyyy-MM-dd\"T\"HH:mm:ss.fff",
  598. "yyyy-MM-dd\"T\"HH:mm:ss.ffzzz",
  599. "yyyy-MM-dd\"T\"HH:mm:ss.ffZ",
  600. "yyyy-MM-dd\"T\"HH:mm:ss.ff",
  601. "yyyy-MM-dd\"T\"HH:mm:ss.fzzz",
  602. "yyyy-MM-dd\"T\"HH:mm:ss.fZ",
  603. "yyyy-MM-dd\"T\"HH:mm:ss.f",
  604. "yyyy-MM-dd",
  605. "--MM-dd"};
  606. }
  607. }
  608. protected override string outputFormat
  609. {
  610. get
  611. {
  612. return "--MM-dd";
  613. }
  614. }
  615. }
  616. private string[] dayAbbrevs = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
  617. private string[] dayNames = {"Sunday", "Monday", "Tuesday",
  618. "Wednesday", "Thursday", "Friday", "Saturday"};
  619. private string[] monthAbbrevs = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  620. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  621. private string[] monthNames = {"January", "February", "March", "April", "May", "June",
  622. "July", "August", "September",
  623. "October", "November", "December"};
  624. /// <summary>
  625. /// Implements the following function
  626. /// string date:date-time()
  627. /// Output format is ISO 8601 (YYYY-MM-DDThh:mm:ss{Z | {+ | -}zz:zz}).
  628. /// YYYY - year with century
  629. /// MM - month in numbers with leading zero
  630. /// DD - day in numbers with leading zero
  631. /// T - the letter T
  632. /// hh - hours in numbers with leading zero (00-23).
  633. /// mm - minutes in numbers with leading zero (00-59).
  634. /// ss - seconds in numbers with leading zero (00-59).
  635. /// +/-zzzz - time zone expressed as hours and minutes from UTC.
  636. /// If UTC, then this is the letter Z
  637. /// If east of Greenwich, then -zz:zz (e.g. Pacific standard time is -08:00)
  638. /// If west of Greenwich, then +zz:zz (e.g. Tokyo is +09:00)
  639. /// </summary>
  640. /// <returns>The current time.</returns>
  641. public string dateTime()
  642. {
  643. DateTimeTZ d = new DateTimeTZ();
  644. return dateTimeImpl(d);
  645. }
  646. /// <summary>
  647. /// This wrapper method will be renamed during custom build
  648. /// to provide conformant EXSLT function name.
  649. /// </summary>
  650. public string dateTime_RENAME_ME()
  651. {
  652. return dateTime();
  653. }
  654. /// <summary>
  655. /// Implements the following function
  656. /// string date:date-time()
  657. /// </summary>
  658. /// <returns>The current date and time or the empty string if the
  659. /// date is invalid </returns>
  660. public string dateTime(string s)
  661. {
  662. try
  663. {
  664. DateTimeTZ d = new DateTimeTZ(s);
  665. return dateTimeImpl(d);
  666. }
  667. catch(FormatException)
  668. {
  669. return "";
  670. }
  671. }
  672. /// <summary>
  673. /// This wrapper method will be renamed during custom build
  674. /// to provide conformant EXSLT function name.
  675. /// </summary>
  676. public string dateTime_RENAME_ME(string d)
  677. {
  678. return dateTime(d);
  679. }
  680. /// <summary>
  681. /// Internal function to format the date based on a date, rather than a string
  682. /// </summary>
  683. /// <returns>The formtted date and time as a ISO8601 string</returns>
  684. internal string dateTimeImpl(DateTimeTZ dtz)
  685. {
  686. return dtz.ToString();
  687. }
  688. /// <summary>
  689. /// Implements the following function
  690. /// string date:date()
  691. /// </summary>
  692. /// <returns>The current date</returns>
  693. public string date()
  694. {
  695. DateTZ dtz = new DateTZ();
  696. return dtz.ToString();
  697. }
  698. /// <summary>
  699. /// Implements the following function
  700. /// string date:date(string)
  701. /// </summary>
  702. /// <returns>The date part of the specified date or the empty string if the
  703. /// date is invalid</returns>
  704. public string date(string d)
  705. {
  706. try
  707. {
  708. DateTZ dtz = new DateTZ(d);
  709. return dtz.ToString();
  710. }
  711. catch(FormatException)
  712. {
  713. return "";
  714. }
  715. }
  716. /// <summary>
  717. /// Implements the following function
  718. /// string date:time()
  719. /// </summary>
  720. /// <returns>The current time</returns>
  721. public string time()
  722. {
  723. TimeTZ t = new TimeTZ();
  724. return t.ToString();
  725. }
  726. /// <summary>
  727. /// Implements the following function
  728. /// string date:time(string)
  729. /// </summary>
  730. /// <returns>The time part of the specified date or the empty string if the
  731. /// date is invalid</returns>
  732. public string time(string d)
  733. {
  734. try
  735. {
  736. TimeTZ t = new TimeTZ(d);
  737. return t.ToString();
  738. }
  739. catch(FormatException)
  740. {
  741. return "";
  742. }
  743. }
  744. /// <summary>
  745. /// Implements the following function
  746. /// number date:year()
  747. /// </summary>
  748. /// <returns>The current year</returns>
  749. public double year()
  750. {
  751. return DateTime.Now.Year;
  752. }
  753. /// <summary>
  754. /// Implements the following function
  755. /// number date:year(string)
  756. /// </summary>
  757. /// <returns>The year part of the specified date or the empty string if the
  758. /// date is invalid</returns>
  759. /// <remarks>Does not support dates in the format of the xs:yearMonth or
  760. /// xs:gYear types</remarks>
  761. public double year(string d)
  762. {
  763. try
  764. {
  765. YearTZ date = new YearTZ(d);
  766. return date.d.Year;
  767. }
  768. catch(FormatException)
  769. {
  770. return System.Double.NaN;
  771. }
  772. }
  773. /// <summary>
  774. /// Helper method for calculating whether a year is a leap year. Algorithm
  775. /// obtained from http://mindprod.com/jglossleapyear.html
  776. /// </summary>
  777. private static bool IsLeapYear (int year)
  778. {
  779. try
  780. {
  781. return CultureInfo.CurrentCulture.Calendar.IsLeapYear(year);
  782. }
  783. catch
  784. {
  785. return false;
  786. }
  787. }
  788. /// <summary>
  789. /// Implements the following function
  790. /// boolean date:leap-year()
  791. /// </summary>
  792. /// <returns>True if the current year is a leap year.</returns>
  793. public bool leapYear()
  794. {
  795. return IsLeapYear((int) year());
  796. }
  797. /// <summary>
  798. /// This wrapper method will be renamed during custom build
  799. /// to provide conformant EXSLT function name.
  800. /// </summary>
  801. public bool leapYear_RENAME_ME()
  802. {
  803. return leapYear();
  804. }
  805. /// <summary>
  806. /// Implements the following function
  807. /// boolean date:leap-year(string)
  808. /// </summary>
  809. /// <returns>True if the specified year is a leap year</returns>
  810. /// <remarks>Note that the spec says we should return NaN for a badly formatted input
  811. /// string. This is impossible; we return false for a badly formatted input string.
  812. /// </remarks>
  813. public bool leapYear(string d)
  814. {
  815. double y = year(d);
  816. if (y == System.Double.NaN)
  817. return false;
  818. else
  819. return IsLeapYear((int)y);
  820. }
  821. /// <summary>
  822. /// This wrapper method will be renamed during custom build
  823. /// to provide conformant EXSLT function name.
  824. /// </summary>
  825. public bool leapYear_RENAME_ME(string d)
  826. {
  827. return leapYear(d);
  828. }
  829. /// <summary>
  830. /// Implements the following function
  831. /// number date:month-in-year()
  832. /// </summary>
  833. /// <returns>The current month</returns>
  834. public double monthInYear()
  835. {
  836. return DateTime.Now.Month;
  837. }
  838. /// <summary>
  839. /// This wrapper method will be renamed during custom build
  840. /// to provide conformant EXSLT function name.
  841. /// </summary>
  842. public double monthInYear_RENAME_ME()
  843. {
  844. return monthInYear();
  845. }
  846. /// <summary>
  847. /// Implements the following function
  848. /// number date:month-in-year(string)
  849. /// </summary>
  850. /// <returns>The month part of the specified date or the empty string if the
  851. /// date is invalid</returns>
  852. /// <remarks>Does not support dates in the format of xs:gYear</remarks>
  853. public double monthInYear(string d)
  854. {
  855. try
  856. {
  857. Month date = new Month(d);
  858. return date.d.Month;
  859. }
  860. catch(FormatException)
  861. {
  862. return System.Double.NaN;
  863. }
  864. }
  865. /// <summary>
  866. /// This wrapper method will be renamed during custom build
  867. /// to provide conformant EXSLT function name.
  868. /// </summary>
  869. public double monthInYear_RENAME_ME(string d)
  870. {
  871. return monthInYear(d);
  872. }
  873. /// <summary>
  874. /// Helper funcitno to calculate the week number
  875. /// </summary>
  876. /// <returns>
  877. /// Returns the week in the year. Obeys EXSLT spec, which specifies that counting follows
  878. /// ISO 8601: week 1 in a year is the week containing the first Thursday of the year, with
  879. /// new weeks beginning on a Monday
  880. /// </returns>
  881. /// <param name="d">The date for which we want to find the week</param>
  882. private double weekInYear(DateTime d)
  883. {
  884. return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(d,
  885. System.Globalization.CalendarWeekRule.FirstFourDayWeek,
  886. System.DayOfWeek.Monday);
  887. }
  888. /// <summary>
  889. /// Implements the following function
  890. /// number date:week-in-year()
  891. /// </summary>
  892. /// <returns>
  893. /// The current week. Obeys EXSLT spec, which specifies that counting follows
  894. /// ISO 8601: week 1 in a year is the week containing the first Thursday of the year, with
  895. /// new weeks beginning on a Monday
  896. /// </returns>
  897. public double weekInYear()
  898. {
  899. return this.weekInYear(DateTime.Now);
  900. }
  901. /// <summary>
  902. /// This wrapper method will be renamed during custom build
  903. /// to provide conformant EXSLT function name.
  904. /// </summary>
  905. public double weekInYear_RENAME_ME()
  906. {
  907. return weekInYear();
  908. }
  909. /// <summary>
  910. /// Implements the following function
  911. /// number date:week-in-year(string)
  912. /// </summary>
  913. /// <returns>The week part of the specified date or the empty string if the
  914. /// date is invalid</returns>
  915. /// <remarks>Does not support dates in the format of the xs:yearMonth or
  916. /// xs:gYear types. This method uses the Calendar.GetWeekOfYear() method
  917. /// with the CalendarWeekRule and FirstDayOfWeek of the current culture.
  918. /// THE RESULTS OF CALLING THIS FUNCTION VARIES ACROSS CULTURES</remarks>
  919. public double weekInYear(string d)
  920. {
  921. try
  922. {
  923. DateTZ dtz = new DateTZ(d);
  924. return weekInYear(dtz.d);
  925. }
  926. catch(FormatException)
  927. {
  928. return System.Double.NaN;
  929. }
  930. }
  931. /// <summary>
  932. /// This wrapper method will be renamed during custom build
  933. /// to provide conformant EXSLT function name.
  934. /// </summary>
  935. public double weekInYear_RENAME_ME(string d)
  936. {
  937. return weekInYear(d);
  938. }
  939. /// <summary>
  940. /// Helper method.
  941. /// </summary>
  942. /// <param name="d"></param>
  943. /// <returns></returns>
  944. private double weekInMonth(DateTime d)
  945. {
  946. //
  947. // mon = 1
  948. // tue = 2
  949. // sun = 7
  950. // week = ceil(((date-day) / 7)) + 1
  951. double offset = (d.DayOfWeek == DayOfWeek.Sunday) ? 7 : (double)d.DayOfWeek;
  952. return System.Math.Ceiling((d.Day-offset) / 7)+1;
  953. }
  954. /// <summary>
  955. /// Implements the following function
  956. /// number date:week-in-month()
  957. /// </summary>
  958. /// <remarks>
  959. /// The current week in month as a number. For the purposes of numbering, the first
  960. /// day of the month is in week 1 and new weeks begin on a Monday (so the first and
  961. /// last weeks in a month will often have less than 7 days in them).
  962. /// </remarks>
  963. public double weekInMonth()
  964. {
  965. return this.weekInMonth(DateTime.Now);
  966. }
  967. /// <summary>
  968. /// This wrapper method will be renamed during custom build
  969. /// to provide conformant EXSLT function name.
  970. /// </summary>
  971. public double weekInMonth_RENAME_ME()
  972. {
  973. return weekInMonth();
  974. }
  975. /// <summary>
  976. /// Implements the following function
  977. /// number date:week-in-month(string)
  978. /// </summary>
  979. /// <returns>The week in month of the specified date or NaN if the
  980. /// date is invalid</returns>
  981. /// <remarks>
  982. /// The current week in month as a number. For the purposes of numbering, the first
  983. /// day of the month is in week 1 and new weeks begin on a Monday (so the first and
  984. /// last weeks in a month will often have less than 7 days in them).
  985. /// </remarks>
  986. public double weekInMonth(string d)
  987. {
  988. try
  989. {
  990. DateTZ date = new DateTZ(d);
  991. return this.weekInMonth(date.d);
  992. }
  993. catch(FormatException)
  994. {
  995. return System.Double.NaN;
  996. }
  997. }
  998. /// <summary>
  999. /// This wrapper method will be renamed during custom build
  1000. /// to provide conformant EXSLT function name.
  1001. /// </summary>
  1002. public double weekInMonth_RENAME_ME(string d)
  1003. {
  1004. return weekInMonth(d);
  1005. }
  1006. /// <summary>
  1007. /// Implements the following function
  1008. /// number date:day-in-year()
  1009. /// </summary>
  1010. /// <returns>The current day. </returns>
  1011. public double dayInYear()
  1012. {
  1013. return DateTime.Now.DayOfYear;
  1014. }
  1015. /// <summary>
  1016. /// This wrapper method will be renamed during custom build
  1017. /// to provide conformant EXSLT function name.
  1018. /// </summary>
  1019. public double dayInYear_RENAME_ME()
  1020. {
  1021. return dayInYear();
  1022. }
  1023. /// <summary>
  1024. /// Implements the following function
  1025. /// number date:day-in-year(string)
  1026. /// </summary>
  1027. /// <returns>
  1028. /// The day part of the specified date or NaN if the date is invalid
  1029. /// </returns>
  1030. public double dayInYear(string d)
  1031. {
  1032. try
  1033. {
  1034. DateTZ date = new DateTZ(d);
  1035. return date.d.DayOfYear;
  1036. }
  1037. catch(FormatException)
  1038. {
  1039. return System.Double.NaN;
  1040. }
  1041. }
  1042. /// <summary>
  1043. /// This wrapper method will be renamed during custom build
  1044. /// to provide conformant EXSLT function name.
  1045. /// </summary>
  1046. public double dayInYear_RENAME_ME(string d)
  1047. {
  1048. return dayInYear(d);
  1049. }
  1050. /// <summary>
  1051. /// Implements the following function
  1052. /// number date:day-in-week()
  1053. /// </summary>
  1054. /// <returns>The current day in the week. 1=Sunday, 2=Monday,...,7=Saturday</returns>
  1055. public double dayInWeek()
  1056. {
  1057. return ((int) DateTime.Now.DayOfWeek) + 1;
  1058. }
  1059. /// <summary>
  1060. /// This wrapper method will be renamed during custom build
  1061. /// to provide conformant EXSLT function name.
  1062. /// </summary>
  1063. public double dayInWeek_RENAME_ME()
  1064. {
  1065. return dayInWeek();
  1066. }
  1067. /// <summary>
  1068. /// Implements the following function
  1069. /// number date:day-in-week(string)
  1070. /// </summary>
  1071. /// <returns>The day in the week of the specified date or NaN if the
  1072. /// date is invalid. The current day in the week. 1=Sunday, 2=Monday,...,7=Saturday
  1073. /// </returns>
  1074. public double dayInWeek(string d)
  1075. {
  1076. try
  1077. {
  1078. DateTZ date = new DateTZ(d);
  1079. return ((int)date.d.DayOfWeek) + 1;
  1080. }
  1081. catch(FormatException)
  1082. {
  1083. return System.Double.NaN;
  1084. }
  1085. }
  1086. /// <summary>
  1087. /// This wrapper method will be renamed during custom build
  1088. /// to provide conformant EXSLT function name.
  1089. /// </summary>
  1090. public double dayInWeek_RENAME_ME(string d)
  1091. {
  1092. return dayInWeek(d);
  1093. }
  1094. /// <summary>
  1095. /// Implements the following function
  1096. /// number date:day-in-month()
  1097. /// </summary>
  1098. /// <returns>The current day. </returns>
  1099. public double dayInMonth()
  1100. {
  1101. return DateTime.Now.Day;
  1102. }
  1103. /// <summary>
  1104. /// This wrapper method will be renamed during custom build
  1105. /// to provide conformant EXSLT function name.
  1106. /// </summary>
  1107. public double dayInMonth_RENAME_ME()
  1108. {
  1109. return dayInMonth();
  1110. }
  1111. /// <summary>
  1112. /// Implements the following function
  1113. /// number date:day-in-month(string)
  1114. /// </summary>
  1115. /// <returns>The day part of the specified date or the empty string if the
  1116. /// date is invalid</returns>
  1117. public double dayInMonth(string d)
  1118. {
  1119. try
  1120. {
  1121. Day date = new Day(d);
  1122. return date.d.Day;
  1123. }
  1124. catch(FormatException)
  1125. {
  1126. return System.Double.NaN;
  1127. }
  1128. }
  1129. /// <summary>
  1130. /// This wrapper method will be renamed during custom build
  1131. /// to provide conformant EXSLT function name.
  1132. /// </summary>
  1133. public double dayInMonth_RENAME_ME(string d)
  1134. {
  1135. return dayInMonth(d);
  1136. }
  1137. /// <summary>
  1138. /// Helper method.
  1139. /// </summary>
  1140. /// <param name="day"></param>
  1141. /// <returns></returns>
  1142. private double dayOfWeekInMonth(int day)
  1143. {
  1144. // day of week in month = floor(((date-1) / 7)) + 1
  1145. return ((day-1)/7) + 1;
  1146. }
  1147. /// <summary>
  1148. /// Implements the following function
  1149. /// number date:day-of-week-in-month()
  1150. /// </summary>
  1151. /// <returns>The current day of week in the month as a number. For instance
  1152. /// the third Friday of the month returns 3</returns>
  1153. public double dayOfWeekInMonth()
  1154. {
  1155. return this.dayOfWeekInMonth(DateTime.Now.Day);
  1156. }
  1157. /// <summary>
  1158. /// This wrapper method will be renamed during custom build
  1159. /// to provide conformant EXSLT function name.
  1160. /// </summary>
  1161. public double dayOfWeekInMonth_RENAME_ME()
  1162. {
  1163. return dayOfWeekInMonth();
  1164. }
  1165. /// <summary>
  1166. /// Implements the following function
  1167. /// number date:day-of-week-in-month(string)
  1168. /// </summary>
  1169. /// <returns>The day part of the specified date or NaN if the
  1170. /// date is invalid</returns>
  1171. public double dayOfWeekInMonth(string d)
  1172. {
  1173. try
  1174. {
  1175. DateTZ date = new DateTZ(d);
  1176. return this.dayOfWeekInMonth(date.d.Day);
  1177. }
  1178. catch(FormatException)
  1179. {
  1180. return System.Double.NaN;
  1181. }
  1182. }
  1183. /// <summary>
  1184. /// This wrapper method will be renamed during custom build
  1185. /// to provide conformant EXSLT function name.
  1186. /// </summary>
  1187. public double dayOfWeekInMonth_RENAME_ME(string d)
  1188. {
  1189. return dayOfWeekInMonth(d);
  1190. }
  1191. /// <summary>
  1192. /// Implements the following function
  1193. /// number date:hour-in-day()
  1194. /// </summary>
  1195. /// <returns>The current hour of the day as a number.</returns>
  1196. public double hourInDay()
  1197. {
  1198. return DateTime.Now.Hour;
  1199. }
  1200. /// <summary>
  1201. /// This wrapper method will be renamed during custom build
  1202. /// to provide conformant EXSLT function name.
  1203. /// </summary>
  1204. public double hourInDay_RENAME_ME()
  1205. {
  1206. return hourInDay();
  1207. }
  1208. /// <summary>
  1209. /// Implements the following function
  1210. /// number date:hour-in-day(string)
  1211. /// </summary>
  1212. /// <returns>The current hour of the specified time or NaN if the
  1213. /// date is invalid</returns>
  1214. public double hourInDay(string d)
  1215. {
  1216. try
  1217. {
  1218. TimeTZ date = new TimeTZ(d);
  1219. return date.d.Hour;
  1220. }
  1221. catch(FormatException)
  1222. {
  1223. return System.Double.NaN;
  1224. }
  1225. }
  1226. /// <summary>
  1227. /// This wrapper method will be renamed during custom build
  1228. /// to provide conformant EXSLT function name.
  1229. /// </summary>
  1230. public double hourInDay_RENAME_ME(string d)
  1231. {
  1232. return hourInDay(d);
  1233. }
  1234. /// <summary>
  1235. /// Implements the following function
  1236. /// number date:minute-in-hour()
  1237. /// </summary>
  1238. /// <returns>The minute of the current hour as a number. </returns>
  1239. public double minuteInHour()
  1240. {
  1241. return DateTime.Now.Minute;
  1242. }
  1243. /// <summary>
  1244. /// This wrapper method will be renamed during custom build
  1245. /// to provide conformant EXSLT function name.
  1246. /// </summary>
  1247. public double minuteInHour_RENAME_ME()
  1248. {
  1249. return minuteInHour();
  1250. }
  1251. /// <summary>
  1252. /// Implements the following function
  1253. /// number date:minute-in-hour(string)
  1254. /// </summary>
  1255. /// <returns>The minute of the hour of the specified time or NaN if the
  1256. /// date is invalid</returns>
  1257. public double minuteInHour(string d)
  1258. {
  1259. try
  1260. {
  1261. TimeTZ date = new TimeTZ(d);
  1262. return date.d.Minute;
  1263. }
  1264. catch(FormatException)
  1265. {
  1266. return System.Double.NaN;
  1267. }
  1268. }
  1269. /// <summary>
  1270. /// This wrapper method will be renamed during custom build
  1271. /// to provide conformant EXSLT function name.
  1272. /// </summary>
  1273. public double minuteInHour_RENAME_ME(string d)
  1274. {
  1275. return minuteInHour(d);
  1276. }
  1277. /// <summary>
  1278. /// Implements the following function
  1279. /// number date:second-in-minute()
  1280. /// </summary>
  1281. /// <returns>The seconds of the current minute as a number. </returns>
  1282. public double secondInMinute()
  1283. {
  1284. return DateTime.Now.Second;
  1285. }
  1286. /// <summary>
  1287. /// This wrapper method will be renamed during custom build
  1288. /// to provide conformant EXSLT function name.
  1289. /// </summary>
  1290. public double secondInMinute_RENAME_ME()
  1291. {
  1292. return secondInMinute();
  1293. }
  1294. /// <summary>
  1295. /// Implements the following function
  1296. /// number date:second-in-minute(string)
  1297. /// </summary>
  1298. /// <returns>The seconds of the minute of the specified time or NaN if the
  1299. /// date is invalid</returns>
  1300. public double secondInMinute(string d)
  1301. {
  1302. try
  1303. {
  1304. TimeTZ date = new TimeTZ(d);
  1305. return date.d.Second;
  1306. }
  1307. catch(FormatException)
  1308. {
  1309. return System.Double.NaN;
  1310. }
  1311. }
  1312. /// <summary>
  1313. /// This wrapper method will be renamed during custom build
  1314. /// to provide conformant EXSLT function name.
  1315. /// </summary>
  1316. public double secondInMinute_RENAME_ME(string d)
  1317. {
  1318. return secondInMinute(d);
  1319. }
  1320. /// <summary>
  1321. /// Helper function for
  1322. /// string date:day-name()
  1323. /// </summary>
  1324. /// <returns>The Engish name of the current day</returns>
  1325. private string dayName(int dow)
  1326. {
  1327. if (dow <0 || dow >= dayNames.Length)
  1328. return String.Empty;
  1329. return dayNames[dow];
  1330. }
  1331. /// <summary>
  1332. /// Implements the following function
  1333. /// string date:day-name()
  1334. /// </summary>
  1335. /// <returns>The Engish name of the current day</returns>
  1336. public string dayName()
  1337. {
  1338. return dayName((int) DateTime.Now.DayOfWeek);
  1339. }
  1340. /// <summary>
  1341. /// This wrapper method will be renamed during custom build
  1342. /// to provide conformant EXSLT function name.
  1343. /// </summary>
  1344. public string dayName_RENAME_ME()
  1345. {
  1346. return dayName();
  1347. }
  1348. /// <summary>
  1349. /// Implements the following function
  1350. /// string date:day-name(string)
  1351. /// </summary>
  1352. /// <returns>The English name of the day of the specified date or the empty string if the
  1353. /// date is invalid</returns>
  1354. public string dayName(string d)
  1355. {
  1356. try
  1357. {
  1358. DateTZ date = new DateTZ(d);
  1359. return dayName((int) date.d.DayOfWeek);
  1360. }
  1361. catch(FormatException)
  1362. {
  1363. return "";
  1364. }
  1365. }
  1366. /// <summary>
  1367. /// This wrapper method will be renamed during custom build
  1368. /// to provide conformant EXSLT function name.
  1369. /// </summary>
  1370. public string dayName_RENAME_ME(string d)
  1371. {
  1372. return dayName(d);
  1373. }
  1374. /// <summary>
  1375. /// Helper function for
  1376. /// string date:day-abbreviation()
  1377. /// </summary>
  1378. /// <returns>The abbreviated English name of the current day</returns>
  1379. private string dayAbbreviation(int dow)
  1380. {
  1381. if (dow < 0 || dow >= dayAbbrevs.Length)
  1382. return String.Empty;
  1383. return dayAbbrevs[dow];
  1384. }
  1385. /// <summary>
  1386. /// Implements the following function
  1387. /// string date:day-abbreviation()
  1388. /// </summary>
  1389. /// <returns>The abbreviated English name of the current day</returns>
  1390. public string dayAbbreviation()
  1391. {
  1392. return dayAbbreviation((int)DateTime.Now.DayOfWeek);
  1393. }
  1394. /// <summary>
  1395. /// This wrapper method will be renamed during custom build
  1396. /// to provide conformant EXSLT function name.
  1397. /// </summary>
  1398. public string dayAbbreviation_RENAME_ME()
  1399. {
  1400. return dayAbbreviation();
  1401. }
  1402. /// <summary>
  1403. /// Implements the following function
  1404. /// string date:day-abbreviation(string)
  1405. /// </summary>
  1406. /// <returns>The abbreviated English name of the day of the specified date or the
  1407. /// empty string if the input date is invalid</returns>
  1408. public string dayAbbreviation(string d)
  1409. {
  1410. try
  1411. {
  1412. DateTZ date = new DateTZ(d);
  1413. return dayAbbreviation((int)date.d.DayOfWeek);
  1414. }
  1415. catch(FormatException)
  1416. {
  1417. return "";
  1418. }
  1419. }
  1420. /// <summary>
  1421. /// This wrapper method will be renamed during custom build
  1422. /// to provide conformant EXSLT function name.
  1423. /// </summary>
  1424. public string dayAbbreviation_RENAME_ME(string d)
  1425. {
  1426. return dayAbbreviation(d);
  1427. }
  1428. /// <summary>
  1429. /// Helper Function for
  1430. /// string date:month-name()
  1431. /// </summary>
  1432. /// <returns>The name of the current month</returns>
  1433. private string monthName(int month)
  1434. {
  1435. if (month < 1 || month > monthNames.Length)
  1436. return String.Empty;
  1437. return monthNames[month-1];
  1438. }
  1439. /// <summary>
  1440. /// Implements the following function
  1441. /// string date:month-name()
  1442. /// </summary>
  1443. /// <returns>The name of the current month</returns>
  1444. public string monthName()
  1445. {
  1446. return monthName((int)monthInYear());
  1447. }
  1448. /// <summary>
  1449. /// This wrapper method will be renamed during custom build
  1450. /// to provide conformant EXSLT function name.
  1451. /// </summary>
  1452. public string monthName_RENAME_ME()
  1453. {
  1454. return monthName();
  1455. }
  1456. /// <summary>
  1457. /// Implements the following function
  1458. /// string date:month-name(string)
  1459. /// </summary>
  1460. /// <returns>The name of the month of the specified date or the empty string if the
  1461. /// date is invalid</returns>
  1462. /// <remarks>Does not support dates in the format of xs:gYear types</remarks>
  1463. public string monthName(string d)
  1464. {
  1465. double month = monthInYear(d);
  1466. if (month == System.Double.NaN)
  1467. return "";
  1468. else
  1469. return monthName((int)month);
  1470. }
  1471. /// <summary>
  1472. /// This wrapper method will be renamed during custom build
  1473. /// to provide conformant EXSLT function name.
  1474. /// </summary>
  1475. public string monthName_RENAME_ME(string d)
  1476. {
  1477. return monthName(d);
  1478. }
  1479. /// <summary>
  1480. /// Helper function for
  1481. /// string date:month-abbreviation()
  1482. /// </summary>
  1483. /// <returns>The abbreviated name of the current month</returns>
  1484. private string monthAbbreviation(int month)
  1485. {
  1486. if (month < 1 || month > monthAbbrevs.Length)
  1487. return String.Empty;
  1488. return monthAbbrevs[month-1];
  1489. }
  1490. /// <summary>
  1491. /// Implements the following function
  1492. /// string date:month-abbreviation()
  1493. /// </summary>
  1494. /// <returns>The abbreviated name of the current month</returns>
  1495. public string monthAbbreviation()
  1496. {
  1497. return monthAbbreviation((int)monthInYear());
  1498. }
  1499. /// <summary>
  1500. /// This wrapper method will be renamed during custom build
  1501. /// to provide conformant EXSLT function name.
  1502. /// </summary>
  1503. public string monthAbbreviation_RENAME_ME()
  1504. {
  1505. return monthAbbreviation();
  1506. }
  1507. /// <summary>
  1508. /// Implements the following function
  1509. /// string date:month-abbreviation(string)
  1510. /// </summary>
  1511. /// <returns>The abbreviated name of the month of the specified date or the empty string if the
  1512. /// date is invalid</returns>
  1513. /// <remarks>Does not support dates in the format of the xs:yearMonth or
  1514. /// xs:gYear types</remarks>
  1515. public string monthAbbreviation(string d)
  1516. {
  1517. double month = monthInYear(d);
  1518. if (month == System.Double.NaN)
  1519. return "";
  1520. else
  1521. return monthAbbreviation((int)month);
  1522. }
  1523. /// <summary>
  1524. /// This wrapper method will be renamed during custom build
  1525. /// to provide conformant EXSLT function name.
  1526. /// </summary>
  1527. public string monthAbbreviation_RENAME_ME(string d)
  1528. {
  1529. return monthAbbreviation(d);
  1530. }
  1531. /// <summary>
  1532. /// Implements the following function
  1533. /// string date:format-date(string, string)
  1534. /// </summary>
  1535. /// <param name="d">The date to format</param>
  1536. /// <param name="format">One of the format strings understood by the
  1537. /// Java 1.1 SimpleDateFormat method:
  1538. ///
  1539. /// Symbol Meaning Presentation Example
  1540. ///------ ------- ------------ -------
  1541. ///G era designator (Text) AD
  1542. ///y year (Number) 1996
  1543. ///M month in year (Text &amp; Number) July &amp; 07
  1544. ///d day in month (Number) 10
  1545. ///h hour in am/pm (1~12) (Number) 12
  1546. ///H hour in day (0~23) (Number) 0
  1547. ///m minute in hour (Number) 30
  1548. ///s second in minute (Number) 55
  1549. ///S millisecond (Number) 978
  1550. ///E day in week (Text) Tuesday
  1551. ///D day in year (Number) 189
  1552. ///F day of week in month (Number) 2 (2nd Wed in July)
  1553. ///w week in year (Number) 27
  1554. ///W week in month (Number) 2
  1555. ///a am/pm marker (Text) PM
  1556. ///k hour in day (1~24) (Number) 24
  1557. ///K hour in am/pm (0~11) (Number) 0
  1558. ///z time zone (Text) Pacific Standard Time
  1559. ///' escape for text (Delimiter)
  1560. ///'' single quote (Literal) '
  1561. ///</param>
  1562. /// <returns>The formated date</returns>
  1563. public string formatDate(string d, string format)
  1564. {
  1565. try
  1566. {
  1567. ExsltDateTime oDate = ExsltDateTimeFactory.ParseDateTime(d);
  1568. StringBuilder retString = new StringBuilder("");
  1569. for (int i=0; i < format.Length;)
  1570. {
  1571. int s = i;
  1572. switch(format[i])
  1573. {
  1574. case 'G':// era designator (Text) AD
  1575. while (i < format.Length && format[i]=='G'){i++;}
  1576. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1577. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1578. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1579. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1580. {
  1581. if (oDate.d.Year < 0)
  1582. {
  1583. retString.Append("BC");
  1584. }
  1585. else
  1586. {
  1587. retString.Append("AD");
  1588. }
  1589. }
  1590. break;
  1591. case 'y':// year (Number) 1996
  1592. while (i < format.Length && format[i]=='y'){i++;}
  1593. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1594. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1595. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1596. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1597. {
  1598. if (i-s == 2)
  1599. {
  1600. retString.Append((oDate.d.Year % 100).ToString().PadLeft(i-s, '0'));
  1601. }
  1602. else
  1603. {
  1604. retString.Append(oDate.d.Year.ToString().PadLeft(i-s, '0'));
  1605. }
  1606. }
  1607. break;
  1608. case 'M':// month in year (Text &amp; Number) July &amp; 07
  1609. while (i < format.Length && format[i]=='M'){i++;}
  1610. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1611. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1612. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1613. Object.ReferenceEquals(oDate.GetType(), typeof(Month)) ||
  1614. Object.ReferenceEquals(oDate.GetType(), typeof(MonthDay)) ||
  1615. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1616. {
  1617. if (i-s <= 2)
  1618. retString.Append(oDate.d.Month.ToString().PadLeft(i-s, '0'));
  1619. else if (i-s == 3)
  1620. retString.Append(monthAbbreviation(oDate.d.Month));
  1621. else
  1622. retString.Append(monthName(oDate.d.Month));
  1623. }
  1624. break;
  1625. case 'd':// day in month (Number) 10
  1626. while (i < format.Length && format[i]=='d'){i++;}
  1627. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1628. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1629. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1630. Object.ReferenceEquals(oDate.GetType(), typeof(MonthDay)) ||
  1631. Object.ReferenceEquals(oDate.GetType(), typeof(Day)) ||
  1632. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1633. {
  1634. retString.Append(oDate.d.Day.ToString().PadLeft(i-s, '0'));
  1635. }
  1636. break;
  1637. case 'h':// hour in am/pm (1~12) (Number) 12
  1638. while (i < format.Length && format[i]=='h'){i++;}
  1639. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1640. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1641. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1642. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1643. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1644. {
  1645. int hour = oDate.d.Hour % 12;
  1646. if (0 == hour)
  1647. hour = 12;
  1648. retString.Append(hour.ToString().PadLeft(i-s, '0'));
  1649. }
  1650. break;
  1651. case 'H':// hour in day (0~23) (Number) 0
  1652. while (i < format.Length && format[i]=='H'){i++;}
  1653. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1654. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1655. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1656. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1657. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1658. {
  1659. retString.Append(oDate.d.Hour.ToString().PadLeft(i-s, '0'));
  1660. }
  1661. break;
  1662. case 'm':// minute in hour (Number) 30
  1663. while (i < format.Length && format[i]=='m'){i++;}
  1664. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1665. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1666. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1667. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1668. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1669. {
  1670. retString.Append(oDate.d.Minute.ToString().PadLeft(i-s, '0'));
  1671. }
  1672. break;
  1673. case 's':// second in minute (Number) 55
  1674. while (i < format.Length && format[i]=='s'){i++;}
  1675. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1676. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1677. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1678. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1679. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1680. {
  1681. retString.Append(oDate.d.Second.ToString().PadLeft(i-s, '0'));
  1682. }
  1683. break;
  1684. case 'S':// millisecond (Number) 978
  1685. while (i < format.Length && format[i]=='S'){i++;}
  1686. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1687. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1688. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1689. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1690. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1691. {
  1692. retString.Append(oDate.d.Millisecond.ToString().PadLeft(i-s, '0'));
  1693. }
  1694. break;
  1695. case 'E':// day in week (Text) Tuesday
  1696. while (i < format.Length && format[i]=='E'){i++;}
  1697. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1698. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1699. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1700. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1701. {
  1702. if (i-s <= 3)
  1703. {
  1704. retString.Append(dayAbbreviation((int)oDate.d.DayOfWeek));
  1705. }
  1706. else
  1707. {
  1708. retString.Append(dayName((int)oDate.d.DayOfWeek));
  1709. }
  1710. }
  1711. break;
  1712. case 'D':// day in year (Number) 189
  1713. while (i < format.Length && format[i]=='D'){i++;}
  1714. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1715. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1716. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1717. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1718. {
  1719. retString.Append(oDate.d.DayOfYear.ToString().PadLeft(i-s, '0'));
  1720. }
  1721. break;
  1722. case 'F':// day of week in month (Number) 2 (2nd Wed in July)
  1723. while (i < format.Length && format[i]=='F'){i++;}
  1724. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1725. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1726. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1727. Object.ReferenceEquals(oDate.GetType(), typeof(MonthDay)) ||
  1728. Object.ReferenceEquals(oDate.GetType(), typeof(Day)) ||
  1729. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1730. {
  1731. retString.Append(dayOfWeekInMonth(oDate.d.Day).ToString().PadLeft(i-s, '0'));
  1732. }
  1733. break;
  1734. case 'w':// week in year (Number) 27
  1735. while (i < format.Length && format[i]=='w'){i++;}
  1736. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1737. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1738. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1739. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1740. {
  1741. retString.Append(weekInYear(oDate.d));
  1742. }
  1743. break;
  1744. case 'W':// week in month (Number) 2
  1745. while (i < format.Length && format[i]=='W'){i++;}
  1746. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1747. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1748. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1749. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1750. {
  1751. retString.Append(weekInMonth(oDate.d));
  1752. }
  1753. break;
  1754. case 'a':// am/pm marker (Text) PM
  1755. while (i < format.Length && format[i]=='a'){i++;}
  1756. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1757. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1758. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1759. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1760. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1761. {
  1762. if (oDate.d.Hour < 12)
  1763. retString.Append("AM");
  1764. else
  1765. retString.Append("PM");
  1766. }
  1767. break;
  1768. case 'k':// hour in day (1~24) (Number) 24
  1769. while (i < format.Length && format[i]=='k'){i++;}
  1770. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1771. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1772. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1773. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1774. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1775. {
  1776. int hour = oDate.d.Hour + 1;
  1777. retString.Append(hour.ToString().PadLeft(i-s, '0'));
  1778. }
  1779. break;
  1780. case 'K':// hour in am/pm (0~11) (Number) 0
  1781. while (i < format.Length && format[i]=='K'){i++;}
  1782. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1783. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1784. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1785. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1786. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1787. {
  1788. int hour = oDate.d.Hour % 12;
  1789. retString.Append(hour.ToString().PadLeft(i-s, '0'));
  1790. }
  1791. break;
  1792. case 'z':// time zone (Text) Pacific Standard Time
  1793. while (i < format.Length && format[i]=='z'){i++;}
  1794. //
  1795. // BUGBUG: Need to convert to full timezone names or timezone abbrevs
  1796. // if they are available. Now cheating by using GMT offsets.
  1797. retString.Append(oDate.GetGMTOffsetTimeZone());
  1798. break;
  1799. case 'Z':// rfc 822 time zone
  1800. while (i < format.Length && format[i]=='Z'){i++;}
  1801. retString.Append(oDate.Get822TimeZone());
  1802. break;
  1803. case '\'':// escape for text (Delimiter)
  1804. if (i < format.Length && format[i+1] == '\'')
  1805. {
  1806. i++;
  1807. while (i < format.Length && format[i]=='\''){i++;}
  1808. retString.Append("'");
  1809. }
  1810. else
  1811. {
  1812. i++;
  1813. while (i < format.Length && format[i]!='\'' && i <= format.Length){retString.Append(format.Substring(i++, 1));}
  1814. if (i >= format.Length)return "";
  1815. i++;
  1816. }
  1817. break;
  1818. default:
  1819. retString.Append(format[i]);
  1820. i++;
  1821. break;
  1822. }
  1823. }
  1824. return retString.ToString();
  1825. }
  1826. catch(FormatException)
  1827. {
  1828. return "";
  1829. }
  1830. }
  1831. /// <summary>
  1832. /// This wrapper method will be renamed during custom build
  1833. /// to provide conformant EXSLT function name.
  1834. /// </summary>
  1835. public string formatDate_RENAME_ME(string d, string format)
  1836. {
  1837. return formatDate(d, format);
  1838. }
  1839. /// <summary>
  1840. /// Implements the following function
  1841. /// string date:parse-date(string, string)
  1842. /// BUGBUG: should use Java formatting strings, not Windows.
  1843. /// </summary>
  1844. /// <param name="d">The date to parse</param>
  1845. /// <param name="format">One of the format strings understood by the
  1846. /// DateTime.ToString(string) method.</param>
  1847. /// <returns>The parsed date</returns>
  1848. public string parseDate(string d, string format)
  1849. {
  1850. try
  1851. {
  1852. DateTime date = DateTime.ParseExact(d, format, CultureInfo.CurrentCulture);
  1853. return XmlConvert.ToString(date);
  1854. }
  1855. catch(FormatException)
  1856. {
  1857. return "";
  1858. }
  1859. }
  1860. /// <summary>
  1861. /// This wrapper method will be renamed during custom build
  1862. /// to provide conformant EXSLT function name.
  1863. /// </summary>
  1864. public string parseDate_RENAME_ME(string d, string format)
  1865. {
  1866. return parseDate(d, format);
  1867. }
  1868. /// <summary>
  1869. /// Implements the following function
  1870. /// string:date:difference(string, string)
  1871. /// </summary>
  1872. /// <param name="start">The start date</param>
  1873. /// <param name="end">The end date</param>
  1874. /// <returns>A positive difference if start is before end otherwise a negative
  1875. /// difference. The difference is in the ISO 8601 date difference format as either
  1876. /// [-]P[yY][mM]
  1877. /// or
  1878. /// [-]P[dD][T][hH][mM][sS]
  1879. /// P means a difference and is required
  1880. /// At least one of Y M D H M S is required
  1881. /// If a higher order component is 0, it is suppressed (for example, if there are 0 years and
  1882. /// 1 month, then Y is suppressed. If there are 1 years and 0 months, M is not suppressed)
  1883. /// If the input format is yyyy-MM or yyyy, then the output is [-]P[yY][mM]
  1884. /// If the input format includes days, hours, minutes or seconds, then the output is
  1885. /// [-]P[dD][T][hH][mM][sS].
  1886. /// If there H M and S are all 0, the T is suppressed.
  1887. /// </returns>
  1888. public string difference(string start, string end)
  1889. {
  1890. try
  1891. {
  1892. ExsltDateTime startdate = ExsltDateTimeFactory.ParseDate(start);
  1893. ExsltDateTime enddate = ExsltDateTimeFactory.ParseDate(end);
  1894. // The rules are pretty tricky. basically, interpret both strings as the least-
  1895. // specific format
  1896. if (Object.ReferenceEquals(startdate.GetType(), typeof(YearTZ)) ||
  1897. Object.ReferenceEquals(enddate.GetType(), typeof(YearTZ)))
  1898. {
  1899. StringBuilder retString = new StringBuilder("");
  1900. int yearDiff = enddate.d.Year - startdate.d.Year;
  1901. if (yearDiff < 0)
  1902. retString.Append('-');
  1903. retString.Append('P');
  1904. retString.Append(Math.Abs(yearDiff));
  1905. retString.Append('Y');
  1906. return retString.ToString();
  1907. }
  1908. else if (Object.ReferenceEquals(startdate.GetType(), typeof(YearMonth)) ||
  1909. Object.ReferenceEquals(enddate.GetType(), typeof(YearMonth)))
  1910. {
  1911. StringBuilder retString = new StringBuilder("");
  1912. int yearDiff = enddate.d.Year - startdate.d.Year;
  1913. int monthDiff = enddate.d.Month - startdate.d.Month;
  1914. // Borrow from the year if necessary
  1915. if ((yearDiff > 0) && (Math.Sign(monthDiff) == -1))
  1916. {
  1917. yearDiff--;
  1918. monthDiff += 12;
  1919. }
  1920. else if ((yearDiff < 0) && (Math.Sign(monthDiff) == 1))
  1921. {
  1922. yearDiff++;
  1923. monthDiff -= 12;
  1924. }
  1925. if ((yearDiff < 0) || ((yearDiff == 0) && (monthDiff < 0)))
  1926. {
  1927. retString.Append('-');
  1928. }
  1929. retString.Append('P');
  1930. if (yearDiff != 0)
  1931. {
  1932. retString.Append(Math.Abs(yearDiff));
  1933. retString.Append('Y');
  1934. }
  1935. retString.Append(Math.Abs(monthDiff));
  1936. retString.Append('M');
  1937. return retString.ToString();
  1938. }
  1939. else
  1940. {
  1941. // Simulate casting to the most truncated format. i.e. if one
  1942. // Arg is DateTZ and the other is DateTimeTZ, get rid of the time
  1943. // for both.
  1944. if (Object.ReferenceEquals(startdate.GetType(), typeof(DateTZ)) ||
  1945. Object.ReferenceEquals(enddate.GetType(), typeof(DateTZ)))
  1946. {
  1947. startdate = new DateTZ(startdate.d.ToString("yyyy-MM-dd"));
  1948. enddate = new DateTZ(enddate.d.ToString("yyyy-MM-dd"));
  1949. }
  1950. TimeSpan ts = enddate.d.Subtract(startdate.d);
  1951. return XmlConvert.ToString(ts);
  1952. }
  1953. }
  1954. catch(FormatException)
  1955. {
  1956. return "";
  1957. }
  1958. }
  1959. /// <summary>
  1960. /// Implements the following function
  1961. /// date:add(string, string)
  1962. /// </summary>
  1963. /// <param name="datetime">An ISO8601 date/time</param>
  1964. /// <param name="duration">the duration to add</param>
  1965. /// <returns>The new time</returns>
  1966. public string add(string datetime, string duration)
  1967. {
  1968. try
  1969. {
  1970. ExsltDateTime date = ExsltDateTimeFactory.ParseDate(datetime);
  1971. //TimeSpan timespan = System.Xml.XmlConvert.ToTimeSpan(duration);
  1972. Regex durationRE = new Regex(
  1973. @"^(-)?" + // May begin with a - sign
  1974. @"P" + // Must contain P as first or 2nd char
  1975. @"(?=\d+|(?:T\d+))" + // Must contain at least one digit after P or after PT
  1976. @"(?:(\d+)Y)?" + // May contain digits plus Y for year
  1977. @"(?:(\d+)M)?" + // May contain digits plus M for month
  1978. @"(?:(\d+)D)?" + // May contain digits plus D for day
  1979. @"(?=T\d+)?" + // If there is a T here, must be digits afterwards
  1980. @"T?" + // May contain a T
  1981. @"(?:(\d+)H)?" + // May contain digits plus H for hours
  1982. @"(?:(\d+)M)?" + // May contain digits plus M for minutes
  1983. @"(?:(\d+)S)?" + // May contain digits plus S for seconds
  1984. @"$",
  1985. RegexOptions.IgnoreCase | RegexOptions.Singleline
  1986. );
  1987. Match m = durationRE.Match(duration);
  1988. int negation = 1, years = 0, months = 0, days = 0,
  1989. hours = 0, minutes = 0, seconds = 0;
  1990. if (m.Success)
  1991. {
  1992. //date.d = date.d.Add(timespan);
  1993. // According to the XML datetime spec at
  1994. // http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes,
  1995. // we need to first add the year/month part, then we can add the
  1996. // day/hour/minute/second part
  1997. if (CultureInfo.InvariantCulture.CompareInfo.Compare(m.Groups[1].Value, "-") == 0)
  1998. negation = -1;
  1999. if (m.Groups[2].Length > 0)
  2000. years = negation * int.Parse(m.Groups[2].Value);
  2001. if (m.Groups[3].Length > 0)
  2002. months = negation * int.Parse(m.Groups[3].Value);
  2003. if (m.Groups[4].Length > 0)
  2004. days = negation * int.Parse(m.Groups[4].Value);
  2005. if (m.Groups[5].Length > 0)
  2006. hours = negation * int.Parse(m.Groups[5].Value);
  2007. if (m.Groups[6].Length > 0)
  2008. minutes = negation * int.Parse(m.Groups[6].Value);
  2009. if (m.Groups[7].Length > 0)
  2010. seconds = negation * int.Parse(m.Groups[7].Value);
  2011. date.d = date.d.AddYears(years);
  2012. date.d = date.d.AddMonths(months);
  2013. date.d = date.d.AddDays(days);
  2014. date.d = date.d.AddHours(hours);
  2015. date.d = date.d.AddMinutes(minutes);
  2016. date.d = date.d.AddSeconds(seconds);
  2017. // we should return the same format as passed in
  2018. // return date.ToString("yyyy-MM-dd\"T\"HH:mm:ss");
  2019. return date.ToString();
  2020. }
  2021. else
  2022. {
  2023. return "";
  2024. }
  2025. }
  2026. catch(FormatException)
  2027. {
  2028. return "";
  2029. }
  2030. }
  2031. /// <summary>
  2032. /// Implements the following function
  2033. /// string:date:add-duration(string, string)
  2034. /// </summary>
  2035. /// <param name="duration1">Initial duration</param>
  2036. /// <param name="duration2">the duration to add</param>
  2037. /// <returns>The new time</returns>
  2038. public string addDuration(string duration1, string duration2)
  2039. {
  2040. try
  2041. {
  2042. TimeSpan timespan1 = XmlConvert.ToTimeSpan(duration1);
  2043. TimeSpan timespan2 = XmlConvert.ToTimeSpan(duration2);
  2044. return XmlConvert.ToString(timespan1.Add(timespan2));
  2045. }
  2046. catch(FormatException)
  2047. {
  2048. return "";
  2049. }
  2050. }
  2051. /// <summary>
  2052. /// This wrapper method will be renamed during custom build
  2053. /// to provide conformant EXSLT function name.
  2054. /// </summary>
  2055. public string addDuration_RENAME_ME(string duration1, string duration2)
  2056. {
  2057. return addDuration(duration1, duration2);
  2058. }
  2059. /// <summary>
  2060. /// Helper method for date:seconds() that takes an ExsltDateTime.
  2061. /// </summary>
  2062. /// <param name="d"></param>
  2063. /// <returns>difference in seconds between the specified date and the
  2064. /// epoch (1970-01-01T00:00:00Z)</returns>
  2065. private double seconds(ExsltDateTime d)
  2066. {
  2067. DateTime epoch = new DateTime(1970, 1, 1, 0,0,0,0, CultureInfo.InvariantCulture.Calendar);
  2068. return d.ToUniversalTime().Subtract(epoch).TotalSeconds;
  2069. }
  2070. /// <summary>
  2071. /// Implements the following function
  2072. /// number date:seconds()
  2073. /// </summary>
  2074. /// <returns>The amount of seconds since the epoch (1970-01-01T00:00:00Z)</returns>
  2075. public double seconds()
  2076. {
  2077. return seconds(new DateTimeTZ());
  2078. }
  2079. /// <summary>
  2080. /// Implements the following function
  2081. /// number date:seconds(string)
  2082. /// </summary>
  2083. /// <returns>If date passed in, the amount of seconds between the specified date and the
  2084. /// epoch (1970-01-01T00:00:00Z). If timespan passed in, returns the number of seconds
  2085. /// in the timespan.</returns>
  2086. public double seconds(string datetime)
  2087. {
  2088. try
  2089. {
  2090. return seconds(ExsltDateTimeFactory.ParseDate(datetime));
  2091. }
  2092. catch(FormatException){ ; } //might be a duration
  2093. try
  2094. {
  2095. TimeSpan duration = XmlConvert.ToTimeSpan(datetime);
  2096. return duration.TotalSeconds;
  2097. }
  2098. catch(FormatException)
  2099. {
  2100. return System.Double.NaN;
  2101. }
  2102. }
  2103. /// <summary>
  2104. /// Implements the following function
  2105. /// string date:sum(node-set)
  2106. /// </summary>
  2107. /// <param name="iterator">Nodeset of timespans</param>
  2108. /// <returns>The sum of the timespans within a node set.</returns>
  2109. public string sum(XPathNodeIterator iterator)
  2110. {
  2111. TimeSpan sum = new TimeSpan(0,0,0,0);
  2112. if(iterator.Count == 0)
  2113. {
  2114. return "";
  2115. }
  2116. try
  2117. {
  2118. while(iterator.MoveNext())
  2119. {
  2120. sum = XmlConvert.ToTimeSpan(iterator.Current.Value).Add(sum);
  2121. }
  2122. }
  2123. catch(FormatException)
  2124. {
  2125. return "";
  2126. }
  2127. return XmlConvert.ToString(sum) ; //XmlConvert.ToString(sum);
  2128. }
  2129. /// <summary>
  2130. /// Implements the following function
  2131. /// string date:duration()
  2132. /// </summary>
  2133. /// <returns>seconds since the beginning of the epoch until now</returns>
  2134. public string duration()
  2135. {
  2136. return duration(seconds());
  2137. }
  2138. /// <summary>
  2139. /// Implements the following function
  2140. /// string date:duration(number)
  2141. /// </summary>
  2142. /// <param name="seconds"></param>
  2143. /// <returns></returns>
  2144. public string duration(double seconds)
  2145. {
  2146. return XmlConvert.ToString(TimeSpan.FromSeconds(seconds));
  2147. }
  2148. }
  2149. }