PageRenderTime 70ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/ESB/Base/ThirdParty/Mvp.Xml-src-2.0/EXSLT/v2/src/Exslt/ExsltDatesAndTimes.cs

#
C# | 2354 lines | 1533 code | 211 blank | 610 comment | 168 complexity | 1806da889beb7cb4a3eb959b889031de MD5 | raw file
Possible License(s): AGPL-3.0, 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. try
  662. {
  663. DateTimeTZ d = new DateTimeTZ(s);
  664. return dateTimeImpl(d);
  665. }
  666. catch(FormatException)
  667. {
  668. return "";
  669. }
  670. }
  671. /// <summary>
  672. /// This wrapper method will be renamed during custom build
  673. /// to provide conformant EXSLT function name.
  674. /// </summary>
  675. public string dateTime_RENAME_ME(string d)
  676. {
  677. return dateTime(d);
  678. }
  679. /// <summary>
  680. /// Internal function to format the date based on a date, rather than a string
  681. /// </summary>
  682. /// <returns>The formtted date and time as a ISO8601 string</returns>
  683. internal string dateTimeImpl(DateTimeTZ dtz)
  684. {
  685. return dtz.ToString();
  686. }
  687. /// <summary>
  688. /// Implements the following function
  689. /// string date:date()
  690. /// </summary>
  691. /// <returns>The current date</returns>
  692. public string date()
  693. {
  694. DateTZ dtz = new DateTZ();
  695. return dtz.ToString();
  696. }
  697. /// <summary>
  698. /// Implements the following function
  699. /// string date:date(string)
  700. /// </summary>
  701. /// <returns>The date part of the specified date or the empty string if the
  702. /// date is invalid</returns>
  703. public string date(string d)
  704. {
  705. try
  706. {
  707. DateTZ dtz = new DateTZ(d);
  708. return dtz.ToString();
  709. }
  710. catch(FormatException)
  711. {
  712. return "";
  713. }
  714. }
  715. /// <summary>
  716. /// Implements the following function
  717. /// string date:time()
  718. /// </summary>
  719. /// <returns>The current time</returns>
  720. public string time()
  721. {
  722. TimeTZ t = new TimeTZ();
  723. return t.ToString();
  724. }
  725. /// <summary>
  726. /// Implements the following function
  727. /// string date:time(string)
  728. /// </summary>
  729. /// <returns>The time part of the specified date or the empty string if the
  730. /// date is invalid</returns>
  731. public string time(string d)
  732. {
  733. try
  734. {
  735. TimeTZ t = new TimeTZ(d);
  736. return t.ToString();
  737. }
  738. catch(FormatException)
  739. {
  740. return "";
  741. }
  742. }
  743. /// <summary>
  744. /// Implements the following function
  745. /// number date:year()
  746. /// </summary>
  747. /// <returns>The current year</returns>
  748. public double year()
  749. {
  750. return DateTime.Now.Year;
  751. }
  752. /// <summary>
  753. /// Implements the following function
  754. /// number date:year(string)
  755. /// </summary>
  756. /// <returns>The year part of the specified date or the empty string if the
  757. /// date is invalid</returns>
  758. /// <remarks>Does not support dates in the format of the xs:yearMonth or
  759. /// xs:gYear types</remarks>
  760. public double year(string d)
  761. {
  762. try
  763. {
  764. YearTZ date = new YearTZ(d);
  765. return date.d.Year;
  766. }
  767. catch(FormatException)
  768. {
  769. return System.Double.NaN;
  770. }
  771. }
  772. /// <summary>
  773. /// Helper method for calculating whether a year is a leap year. Algorithm
  774. /// obtained from http://mindprod.com/jglossleapyear.html
  775. /// </summary>
  776. private static bool IsLeapYear (int year)
  777. {
  778. try
  779. {
  780. return CultureInfo.CurrentCulture.Calendar.IsLeapYear(year);
  781. }
  782. catch
  783. {
  784. return false;
  785. }
  786. }
  787. /// <summary>
  788. /// Implements the following function
  789. /// boolean date:leap-year()
  790. /// </summary>
  791. /// <returns>True if the current year is a leap year.</returns>
  792. public bool leapYear()
  793. {
  794. return IsLeapYear((int) year());
  795. }
  796. /// <summary>
  797. /// This wrapper method will be renamed during custom build
  798. /// to provide conformant EXSLT function name.
  799. /// </summary>
  800. public bool leapYear_RENAME_ME()
  801. {
  802. return leapYear();
  803. }
  804. /// <summary>
  805. /// Implements the following function
  806. /// boolean date:leap-year(string)
  807. /// </summary>
  808. /// <returns>True if the specified year is a leap year</returns>
  809. /// <remarks>Note that the spec says we should return NaN for a badly formatted input
  810. /// string. This is impossible; we return false for a badly formatted input string.
  811. /// </remarks>
  812. public bool leapYear(string d)
  813. {
  814. double y = year(d);
  815. if (y == System.Double.NaN)
  816. return false;
  817. else
  818. return IsLeapYear((int)y);
  819. }
  820. /// <summary>
  821. /// This wrapper method will be renamed during custom build
  822. /// to provide conformant EXSLT function name.
  823. /// </summary>
  824. public bool leapYear_RENAME_ME(string d)
  825. {
  826. return leapYear(d);
  827. }
  828. /// <summary>
  829. /// Implements the following function
  830. /// number date:month-in-year()
  831. /// </summary>
  832. /// <returns>The current month</returns>
  833. public double monthInYear()
  834. {
  835. return DateTime.Now.Month;
  836. }
  837. /// <summary>
  838. /// This wrapper method will be renamed during custom build
  839. /// to provide conformant EXSLT function name.
  840. /// </summary>
  841. public double monthInYear_RENAME_ME()
  842. {
  843. return monthInYear();
  844. }
  845. /// <summary>
  846. /// Implements the following function
  847. /// number date:month-in-year(string)
  848. /// </summary>
  849. /// <returns>The month part of the specified date or the empty string if the
  850. /// date is invalid</returns>
  851. /// <remarks>Does not support dates in the format of xs:gYear</remarks>
  852. public double monthInYear(string d)
  853. {
  854. try
  855. {
  856. Month date = new Month(d);
  857. return date.d.Month;
  858. }
  859. catch(FormatException)
  860. {
  861. return System.Double.NaN;
  862. }
  863. }
  864. /// <summary>
  865. /// This wrapper method will be renamed during custom build
  866. /// to provide conformant EXSLT function name.
  867. /// </summary>
  868. public double monthInYear_RENAME_ME(string d)
  869. {
  870. return monthInYear(d);
  871. }
  872. /// <summary>
  873. /// Helper funcitno to calculate the week number
  874. /// </summary>
  875. /// <returns>
  876. /// Returns the week in the year. Obeys EXSLT spec, which specifies that counting follows
  877. /// ISO 8601: week 1 in a year is the week containing the first Thursday of the year, with
  878. /// new weeks beginning on a Monday
  879. /// </returns>
  880. /// <param name="d">The date for which we want to find the week</param>
  881. private double weekInYear(DateTime d)
  882. {
  883. return CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(d,
  884. System.Globalization.CalendarWeekRule.FirstFourDayWeek,
  885. System.DayOfWeek.Monday);
  886. }
  887. /// <summary>
  888. /// Implements the following function
  889. /// number date:week-in-year()
  890. /// </summary>
  891. /// <returns>
  892. /// The current week. Obeys EXSLT spec, which specifies that counting follows
  893. /// ISO 8601: week 1 in a year is the week containing the first Thursday of the year, with
  894. /// new weeks beginning on a Monday
  895. /// </returns>
  896. public double weekInYear()
  897. {
  898. return this.weekInYear(DateTime.Now);
  899. }
  900. /// <summary>
  901. /// This wrapper method will be renamed during custom build
  902. /// to provide conformant EXSLT function name.
  903. /// </summary>
  904. public double weekInYear_RENAME_ME()
  905. {
  906. return weekInYear();
  907. }
  908. /// <summary>
  909. /// Implements the following function
  910. /// number date:week-in-year(string)
  911. /// </summary>
  912. /// <returns>The week part of the specified date or the empty string if the
  913. /// date is invalid</returns>
  914. /// <remarks>Does not support dates in the format of the xs:yearMonth or
  915. /// xs:gYear types. This method uses the Calendar.GetWeekOfYear() method
  916. /// with the CalendarWeekRule and FirstDayOfWeek of the current culture.
  917. /// THE RESULTS OF CALLING THIS FUNCTION VARIES ACROSS CULTURES</remarks>
  918. public double weekInYear(string d)
  919. {
  920. try
  921. {
  922. DateTZ dtz = new DateTZ(d);
  923. return weekInYear(dtz.d);
  924. }
  925. catch(FormatException)
  926. {
  927. return System.Double.NaN;
  928. }
  929. }
  930. /// <summary>
  931. /// This wrapper method will be renamed during custom build
  932. /// to provide conformant EXSLT function name.
  933. /// </summary>
  934. public double weekInYear_RENAME_ME(string d)
  935. {
  936. return weekInYear(d);
  937. }
  938. /// <summary>
  939. /// Helper method.
  940. /// </summary>
  941. /// <param name="d"></param>
  942. /// <returns></returns>
  943. private double weekInMonth(DateTime d)
  944. {
  945. //
  946. // mon = 1
  947. // tue = 2
  948. // sun = 7
  949. // week = ceil(((date-day) / 7)) + 1
  950. double offset = (d.DayOfWeek == DayOfWeek.Sunday) ? 7 : (double)d.DayOfWeek;
  951. return System.Math.Ceiling((d.Day-offset) / 7)+1;
  952. }
  953. /// <summary>
  954. /// Implements the following function
  955. /// number date:week-in-month()
  956. /// </summary>
  957. /// <remarks>
  958. /// The current week in month as a number. For the purposes of numbering, the first
  959. /// day of the month is in week 1 and new weeks begin on a Monday (so the first and
  960. /// last weeks in a month will often have less than 7 days in them).
  961. /// </remarks>
  962. public double weekInMonth()
  963. {
  964. return this.weekInMonth(DateTime.Now);
  965. }
  966. /// <summary>
  967. /// This wrapper method will be renamed during custom build
  968. /// to provide conformant EXSLT function name.
  969. /// </summary>
  970. public double weekInMonth_RENAME_ME()
  971. {
  972. return weekInMonth();
  973. }
  974. /// <summary>
  975. /// Implements the following function
  976. /// number date:week-in-month(string)
  977. /// </summary>
  978. /// <returns>The week in month of the specified date or NaN if the
  979. /// date is invalid</returns>
  980. /// <remarks>
  981. /// The current week in month as a number. For the purposes of numbering, the first
  982. /// day of the month is in week 1 and new weeks begin on a Monday (so the first and
  983. /// last weeks in a month will often have less than 7 days in them).
  984. /// </remarks>
  985. public double weekInMonth(string d)
  986. {
  987. try
  988. {
  989. DateTZ date = new DateTZ(d);
  990. return this.weekInMonth(date.d);
  991. }
  992. catch(FormatException)
  993. {
  994. return System.Double.NaN;
  995. }
  996. }
  997. /// <summary>
  998. /// This wrapper method will be renamed during custom build
  999. /// to provide conformant EXSLT function name.
  1000. /// </summary>
  1001. public double weekInMonth_RENAME_ME(string d)
  1002. {
  1003. return weekInMonth(d);
  1004. }
  1005. /// <summary>
  1006. /// Implements the following function
  1007. /// number date:day-in-year()
  1008. /// </summary>
  1009. /// <returns>The current day. </returns>
  1010. public double dayInYear()
  1011. {
  1012. return DateTime.Now.DayOfYear;
  1013. }
  1014. /// <summary>
  1015. /// This wrapper method will be renamed during custom build
  1016. /// to provide conformant EXSLT function name.
  1017. /// </summary>
  1018. public double dayInYear_RENAME_ME()
  1019. {
  1020. return dayInYear();
  1021. }
  1022. /// <summary>
  1023. /// Implements the following function
  1024. /// number date:day-in-year(string)
  1025. /// </summary>
  1026. /// <returns>
  1027. /// The day part of the specified date or NaN if the date is invalid
  1028. /// </returns>
  1029. public double dayInYear(string d)
  1030. {
  1031. try
  1032. {
  1033. DateTZ date = new DateTZ(d);
  1034. return date.d.DayOfYear;
  1035. }
  1036. catch(FormatException)
  1037. {
  1038. return System.Double.NaN;
  1039. }
  1040. }
  1041. /// <summary>
  1042. /// This wrapper method will be renamed during custom build
  1043. /// to provide conformant EXSLT function name.
  1044. /// </summary>
  1045. public double dayInYear_RENAME_ME(string d)
  1046. {
  1047. return dayInYear(d);
  1048. }
  1049. /// <summary>
  1050. /// Implements the following function
  1051. /// number date:day-in-week()
  1052. /// </summary>
  1053. /// <returns>The current day in the week. 1=Sunday, 2=Monday,...,7=Saturday</returns>
  1054. public double dayInWeek()
  1055. {
  1056. return ((int) DateTime.Now.DayOfWeek) + 1;
  1057. }
  1058. /// <summary>
  1059. /// This wrapper method will be renamed during custom build
  1060. /// to provide conformant EXSLT function name.
  1061. /// </summary>
  1062. public double dayInWeek_RENAME_ME()
  1063. {
  1064. return dayInWeek();
  1065. }
  1066. /// <summary>
  1067. /// Implements the following function
  1068. /// number date:day-in-week(string)
  1069. /// </summary>
  1070. /// <returns>The day in the week of the specified date or NaN if the
  1071. /// date is invalid. The current day in the week. 1=Sunday, 2=Monday,...,7=Saturday
  1072. /// </returns>
  1073. public double dayInWeek(string d){
  1074. try
  1075. {
  1076. DateTZ date = new DateTZ(d);
  1077. return ((int)date.d.DayOfWeek) + 1;
  1078. }
  1079. catch(FormatException)
  1080. {
  1081. return System.Double.NaN;
  1082. }
  1083. }
  1084. /// <summary>
  1085. /// This wrapper method will be renamed during custom build
  1086. /// to provide conformant EXSLT function name.
  1087. /// </summary>
  1088. public double dayInWeek_RENAME_ME(string d)
  1089. {
  1090. return dayInWeek(d);
  1091. }
  1092. /// <summary>
  1093. /// Implements the following function
  1094. /// number date:day-in-month()
  1095. /// </summary>
  1096. /// <returns>The current day. </returns>
  1097. public double dayInMonth()
  1098. {
  1099. return DateTime.Now.Day;
  1100. }
  1101. /// <summary>
  1102. /// This wrapper method will be renamed during custom build
  1103. /// to provide conformant EXSLT function name.
  1104. /// </summary>
  1105. public double dayInMonth_RENAME_ME()
  1106. {
  1107. return dayInMonth();
  1108. }
  1109. /// <summary>
  1110. /// Implements the following function
  1111. /// number date:day-in-month(string)
  1112. /// </summary>
  1113. /// <returns>The day part of the specified date or the empty string if the
  1114. /// date is invalid</returns>
  1115. public double dayInMonth(string d)
  1116. {
  1117. try
  1118. {
  1119. Day date = new Day(d);
  1120. return date.d.Day;
  1121. }
  1122. catch(FormatException)
  1123. {
  1124. return System.Double.NaN;
  1125. }
  1126. }
  1127. /// <summary>
  1128. /// This wrapper method will be renamed during custom build
  1129. /// to provide conformant EXSLT function name.
  1130. /// </summary>
  1131. public double dayInMonth_RENAME_ME(string d)
  1132. {
  1133. return dayInMonth(d);
  1134. }
  1135. /// <summary>
  1136. /// Helper method.
  1137. /// </summary>
  1138. /// <param name="day"></param>
  1139. /// <returns></returns>
  1140. private double dayOfWeekInMonth(int day)
  1141. {
  1142. // day of week in month = floor(((date-1) / 7)) + 1
  1143. return ((day-1)/7) + 1;
  1144. }
  1145. /// <summary>
  1146. /// Implements the following function
  1147. /// number date:day-of-week-in-month()
  1148. /// </summary>
  1149. /// <returns>The current day of week in the month as a number. For instance
  1150. /// the third Friday of the month returns 3</returns>
  1151. public double dayOfWeekInMonth()
  1152. {
  1153. return this.dayOfWeekInMonth(DateTime.Now.Day);
  1154. }
  1155. /// <summary>
  1156. /// This wrapper method will be renamed during custom build
  1157. /// to provide conformant EXSLT function name.
  1158. /// </summary>
  1159. public double dayOfWeekInMonth_RENAME_ME()
  1160. {
  1161. return dayOfWeekInMonth();
  1162. }
  1163. /// <summary>
  1164. /// Implements the following function
  1165. /// number date:day-of-week-in-month(string)
  1166. /// </summary>
  1167. /// <returns>The day part of the specified date or NaN if the
  1168. /// date is invalid</returns>
  1169. public double dayOfWeekInMonth(string d)
  1170. {
  1171. try
  1172. {
  1173. DateTZ date = new DateTZ(d);
  1174. return this.dayOfWeekInMonth(date.d.Day);
  1175. }
  1176. catch(FormatException)
  1177. {
  1178. return System.Double.NaN;
  1179. }
  1180. }
  1181. /// <summary>
  1182. /// This wrapper method will be renamed during custom build
  1183. /// to provide conformant EXSLT function name.
  1184. /// </summary>
  1185. public double dayOfWeekInMonth_RENAME_ME(string d)
  1186. {
  1187. return dayOfWeekInMonth(d);
  1188. }
  1189. /// <summary>
  1190. /// Implements the following function
  1191. /// number date:hour-in-day()
  1192. /// </summary>
  1193. /// <returns>The current hour of the day as a number.</returns>
  1194. public double hourInDay()
  1195. {
  1196. return DateTime.Now.Hour;
  1197. }
  1198. /// <summary>
  1199. /// This wrapper method will be renamed during custom build
  1200. /// to provide conformant EXSLT function name.
  1201. /// </summary>
  1202. public double hourInDay_RENAME_ME()
  1203. {
  1204. return hourInDay();
  1205. }
  1206. /// <summary>
  1207. /// Implements the following function
  1208. /// number date:hour-in-day(string)
  1209. /// </summary>
  1210. /// <returns>The current hour of the specified time or NaN if the
  1211. /// date is invalid</returns>
  1212. public double hourInDay(string d)
  1213. {
  1214. try
  1215. {
  1216. TimeTZ date = new TimeTZ(d);
  1217. return date.d.Hour;
  1218. }
  1219. catch(FormatException)
  1220. {
  1221. return System.Double.NaN;
  1222. }
  1223. }
  1224. /// <summary>
  1225. /// This wrapper method will be renamed during custom build
  1226. /// to provide conformant EXSLT function name.
  1227. /// </summary>
  1228. public double hourInDay_RENAME_ME(string d)
  1229. {
  1230. return hourInDay(d);
  1231. }
  1232. /// <summary>
  1233. /// Implements the following function
  1234. /// number date:minute-in-hour()
  1235. /// </summary>
  1236. /// <returns>The minute of the current hour as a number. </returns>
  1237. public double minuteInHour()
  1238. {
  1239. return DateTime.Now.Minute;
  1240. }
  1241. /// <summary>
  1242. /// This wrapper method will be renamed during custom build
  1243. /// to provide conformant EXSLT function name.
  1244. /// </summary>
  1245. public double minuteInHour_RENAME_ME()
  1246. {
  1247. return minuteInHour();
  1248. }
  1249. /// <summary>
  1250. /// Implements the following function
  1251. /// number date:minute-in-hour(string)
  1252. /// </summary>
  1253. /// <returns>The minute of the hour of the specified time or NaN if the
  1254. /// date is invalid</returns>
  1255. public double minuteInHour(string d)
  1256. {
  1257. try
  1258. {
  1259. TimeTZ date = new TimeTZ(d);
  1260. return date.d.Minute;
  1261. }
  1262. catch(FormatException)
  1263. {
  1264. return System.Double.NaN;
  1265. }
  1266. }
  1267. /// <summary>
  1268. /// This wrapper method will be renamed during custom build
  1269. /// to provide conformant EXSLT function name.
  1270. /// </summary>
  1271. public double minuteInHour_RENAME_ME(string d)
  1272. {
  1273. return minuteInHour(d);
  1274. }
  1275. /// <summary>
  1276. /// Implements the following function
  1277. /// number date:second-in-minute()
  1278. /// </summary>
  1279. /// <returns>The seconds of the current minute as a number. </returns>
  1280. public double secondInMinute()
  1281. {
  1282. return DateTime.Now.Second;
  1283. }
  1284. /// <summary>
  1285. /// This wrapper method will be renamed during custom build
  1286. /// to provide conformant EXSLT function name.
  1287. /// </summary>
  1288. public double secondInMinute_RENAME_ME()
  1289. {
  1290. return secondInMinute();
  1291. }
  1292. /// <summary>
  1293. /// Implements the following function
  1294. /// number date:second-in-minute(string)
  1295. /// </summary>
  1296. /// <returns>The seconds of the minute of the specified time or NaN if the
  1297. /// date is invalid</returns>
  1298. public double secondInMinute(string d)
  1299. {
  1300. try
  1301. {
  1302. TimeTZ date = new TimeTZ(d);
  1303. return date.d.Second;
  1304. }
  1305. catch(FormatException)
  1306. {
  1307. return System.Double.NaN;
  1308. }
  1309. }
  1310. /// <summary>
  1311. /// This wrapper method will be renamed during custom build
  1312. /// to provide conformant EXSLT function name.
  1313. /// </summary>
  1314. public double secondInMinute_RENAME_ME(string d)
  1315. {
  1316. return secondInMinute(d);
  1317. }
  1318. /// <summary>
  1319. /// Helper function for
  1320. /// string date:day-name()
  1321. /// </summary>
  1322. /// <returns>The Engish name of the current day</returns>
  1323. private string dayName(int dow)
  1324. {
  1325. if (dow <0 || dow >= dayNames.Length)
  1326. return String.Empty;
  1327. return dayNames[dow];
  1328. }
  1329. /// <summary>
  1330. /// Implements the following function
  1331. /// string date:day-name()
  1332. /// </summary>
  1333. /// <returns>The Engish name of the current day</returns>
  1334. public string dayName()
  1335. {
  1336. return dayName((int) DateTime.Now.DayOfWeek);
  1337. }
  1338. /// <summary>
  1339. /// This wrapper method will be renamed during custom build
  1340. /// to provide conformant EXSLT function name.
  1341. /// </summary>
  1342. public string dayName_RENAME_ME()
  1343. {
  1344. return dayName();
  1345. }
  1346. /// <summary>
  1347. /// Implements the following function
  1348. /// string date:day-name(string)
  1349. /// </summary>
  1350. /// <returns>The English name of the day of the specified date or the empty string if the
  1351. /// date is invalid</returns>
  1352. public string dayName(string d)
  1353. {
  1354. try
  1355. {
  1356. DateTZ date = new DateTZ(d);
  1357. return dayName((int) date.d.DayOfWeek);
  1358. }
  1359. catch(FormatException)
  1360. {
  1361. return "";
  1362. }
  1363. }
  1364. /// <summary>
  1365. /// This wrapper method will be renamed during custom build
  1366. /// to provide conformant EXSLT function name.
  1367. /// </summary>
  1368. public string dayName_RENAME_ME(string d)
  1369. {
  1370. return dayName(d);
  1371. }
  1372. /// <summary>
  1373. /// Helper function for
  1374. /// string date:day-abbreviation()
  1375. /// </summary>
  1376. /// <returns>The abbreviated English name of the current day</returns>
  1377. private string dayAbbreviation(int dow)
  1378. {
  1379. if (dow < 0 || dow >= dayAbbrevs.Length)
  1380. return String.Empty;
  1381. return dayAbbrevs[dow];
  1382. }
  1383. /// <summary>
  1384. /// Implements the following function
  1385. /// string date:day-abbreviation()
  1386. /// </summary>
  1387. /// <returns>The abbreviated English name of the current day</returns>
  1388. public string dayAbbreviation()
  1389. {
  1390. return dayAbbreviation((int)DateTime.Now.DayOfWeek);
  1391. }
  1392. /// <summary>
  1393. /// This wrapper method will be renamed during custom build
  1394. /// to provide conformant EXSLT function name.
  1395. /// </summary>
  1396. public string dayAbbreviation_RENAME_ME()
  1397. {
  1398. return dayAbbreviation();
  1399. }
  1400. /// <summary>
  1401. /// Implements the following function
  1402. /// string date:day-abbreviation(string)
  1403. /// </summary>
  1404. /// <returns>The abbreviated English name of the day of the specified date or the
  1405. /// empty string if the input date is invalid</returns>
  1406. public string dayAbbreviation(string d)
  1407. {
  1408. try
  1409. {
  1410. DateTZ date = new DateTZ(d);
  1411. return dayAbbreviation((int)date.d.DayOfWeek);
  1412. }
  1413. catch(FormatException)
  1414. {
  1415. return "";
  1416. }
  1417. }
  1418. /// <summary>
  1419. /// This wrapper method will be renamed during custom build
  1420. /// to provide conformant EXSLT function name.
  1421. /// </summary>
  1422. public string dayAbbreviation_RENAME_ME(string d)
  1423. {
  1424. return dayAbbreviation(d);
  1425. }
  1426. /// <summary>
  1427. /// Helper Function for
  1428. /// string date:month-name()
  1429. /// </summary>
  1430. /// <returns>The name of the current month</returns>
  1431. private string monthName(int month)
  1432. {
  1433. if (month < 1 || month > monthNames.Length)
  1434. return String.Empty;
  1435. return monthNames[month-1];
  1436. }
  1437. /// <summary>
  1438. /// Implements the following function
  1439. /// string date:month-name()
  1440. /// </summary>
  1441. /// <returns>The name of the current month</returns>
  1442. public string monthName()
  1443. {
  1444. return monthName((int)monthInYear());
  1445. }
  1446. /// <summary>
  1447. /// This wrapper method will be renamed during custom build
  1448. /// to provide conformant EXSLT function name.
  1449. /// </summary>
  1450. public string monthName_RENAME_ME()
  1451. {
  1452. return monthName();
  1453. }
  1454. /// <summary>
  1455. /// Implements the following function
  1456. /// string date:month-name(string)
  1457. /// </summary>
  1458. /// <returns>The name of the month of the specified date or the empty string if the
  1459. /// date is invalid</returns>
  1460. /// <remarks>Does not support dates in the format of xs:gYear types</remarks>
  1461. public string monthName(string d)
  1462. {
  1463. double month = monthInYear(d);
  1464. if (month == System.Double.NaN)
  1465. return "";
  1466. else
  1467. return monthName((int)month);
  1468. }
  1469. /// <summary>
  1470. /// This wrapper method will be renamed during custom build
  1471. /// to provide conformant EXSLT function name.
  1472. /// </summary>
  1473. public string monthName_RENAME_ME(string d)
  1474. {
  1475. return monthName(d);
  1476. }
  1477. /// <summary>
  1478. /// Helper function for
  1479. /// string date:month-abbreviation()
  1480. /// </summary>
  1481. /// <returns>The abbreviated name of the current month</returns>
  1482. private string monthAbbreviation(int month)
  1483. {
  1484. if (month < 1 || month > monthAbbrevs.Length)
  1485. return String.Empty;
  1486. return monthAbbrevs[month-1];
  1487. }
  1488. /// <summary>
  1489. /// Implements the following function
  1490. /// string date:month-abbreviation()
  1491. /// </summary>
  1492. /// <returns>The abbreviated name of the current month</returns>
  1493. public string monthAbbreviation()
  1494. {
  1495. return monthAbbreviation((int)monthInYear());
  1496. }
  1497. /// <summary>
  1498. /// This wrapper method will be renamed during custom build
  1499. /// to provide conformant EXSLT function name.
  1500. /// </summary>
  1501. public string monthAbbreviation_RENAME_ME()
  1502. {
  1503. return monthAbbreviation();
  1504. }
  1505. /// <summary>
  1506. /// Implements the following function
  1507. /// string date:month-abbreviation(string)
  1508. /// </summary>
  1509. /// <returns>The abbreviated name of the month of the specified date or the empty string if the
  1510. /// date is invalid</returns>
  1511. /// <remarks>Does not support dates in the format of the xs:yearMonth or
  1512. /// xs:gYear types</remarks>
  1513. public string monthAbbreviation(string d)
  1514. {
  1515. double month = monthInYear(d);
  1516. if (month == System.Double.NaN)
  1517. return "";
  1518. else
  1519. return monthAbbreviation((int)month);
  1520. }
  1521. /// <summary>
  1522. /// This wrapper method will be renamed during custom build
  1523. /// to provide conformant EXSLT function name.
  1524. /// </summary>
  1525. public string monthAbbreviation_RENAME_ME(string d)
  1526. {
  1527. return monthAbbreviation(d);
  1528. }
  1529. /// <summary>
  1530. /// Implements the following function
  1531. /// string date:format-date(string, string)
  1532. /// </summary>
  1533. /// <param name="d">The date to format</param>
  1534. /// <param name="format">One of the format strings understood by the
  1535. /// Java 1.1 SimpleDateFormat method:
  1536. ///
  1537. /// Symbol Meaning Presentation Example
  1538. ///------ ------- ------------ -------
  1539. ///G era designator (Text) AD
  1540. ///y year (Number) 1996
  1541. ///M month in year (Text &amp; Number) July &amp; 07
  1542. ///d day in month (Number) 10
  1543. ///h hour in am/pm (1~12) (Number) 12
  1544. ///H hour in day (0~23) (Number) 0
  1545. ///m minute in hour (Number) 30
  1546. ///s second in minute (Number) 55
  1547. ///S millisecond (Number) 978
  1548. ///E day in week (Text) Tuesday
  1549. ///D day in year (Number) 189
  1550. ///F day of week in month (Number) 2 (2nd Wed in July)
  1551. ///w week in year (Number) 27
  1552. ///W week in month (Number) 2
  1553. ///a am/pm marker (Text) PM
  1554. ///k hour in day (1~24) (Number) 24
  1555. ///K hour in am/pm (0~11) (Number) 0
  1556. ///z time zone (Text) Pacific Standard Time
  1557. ///' escape for text (Delimiter)
  1558. ///'' single quote (Literal) '
  1559. ///</param>
  1560. /// <returns>The formated date</returns>
  1561. public string formatDate(string d, string format)
  1562. {
  1563. try
  1564. {
  1565. ExsltDateTime oDate = ExsltDateTimeFactory.ParseDateTime(d);
  1566. StringBuilder retString = new StringBuilder("");
  1567. for (int i=0; i < format.Length;)
  1568. {
  1569. int s = i;
  1570. switch(format[i])
  1571. {
  1572. case 'G':// era designator (Text) AD
  1573. while (i < format.Length && format[i]=='G'){i++;}
  1574. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1575. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1576. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1577. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1578. {
  1579. if (oDate.d.Year < 0)
  1580. {
  1581. retString.Append("BC");
  1582. }
  1583. else
  1584. {
  1585. retString.Append("AD");
  1586. }
  1587. }
  1588. break;
  1589. case 'y':// year (Number) 1996
  1590. while (i < format.Length && format[i]=='y'){i++;}
  1591. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1592. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1593. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1594. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1595. {
  1596. if (i-s == 2)
  1597. {
  1598. retString.Append((oDate.d.Year % 100).ToString().PadLeft(i-s, '0'));
  1599. }
  1600. else
  1601. {
  1602. retString.Append(oDate.d.Year.ToString().PadLeft(i-s, '0'));
  1603. }
  1604. }
  1605. break;
  1606. case 'M':// month in year (Text &amp; Number) July &amp; 07
  1607. while (i < format.Length && format[i]=='M'){i++;}
  1608. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1609. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1610. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1611. Object.ReferenceEquals(oDate.GetType(), typeof(Month)) ||
  1612. Object.ReferenceEquals(oDate.GetType(), typeof(MonthDay)) ||
  1613. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1614. {
  1615. if (i-s <= 2)
  1616. retString.Append(oDate.d.Month.ToString().PadLeft(i-s, '0'));
  1617. else if (i-s == 3)
  1618. retString.Append(monthAbbreviation(oDate.d.Month));
  1619. else
  1620. retString.Append(monthName(oDate.d.Month));
  1621. }
  1622. break;
  1623. case 'd':// day in month (Number) 10
  1624. while (i < format.Length && format[i]=='d'){i++;}
  1625. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1626. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1627. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1628. Object.ReferenceEquals(oDate.GetType(), typeof(MonthDay)) ||
  1629. Object.ReferenceEquals(oDate.GetType(), typeof(Day)) ||
  1630. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1631. {
  1632. retString.Append(oDate.d.Day.ToString().PadLeft(i-s, '0'));
  1633. }
  1634. break;
  1635. case 'h':// hour in am/pm (1~12) (Number) 12
  1636. while (i < format.Length && format[i]=='h'){i++;}
  1637. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1638. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1639. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1640. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1641. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1642. {
  1643. int hour = oDate.d.Hour % 12;
  1644. if (0 == hour)
  1645. hour = 12;
  1646. retString.Append(hour.ToString().PadLeft(i-s, '0'));
  1647. }
  1648. break;
  1649. case 'H':// hour in day (0~23) (Number) 0
  1650. while (i < format.Length && format[i]=='H'){i++;}
  1651. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1652. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1653. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1654. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1655. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1656. {
  1657. retString.Append(oDate.d.Hour.ToString().PadLeft(i-s, '0'));
  1658. }
  1659. break;
  1660. case 'm':// minute in hour (Number) 30
  1661. while (i < format.Length && format[i]=='m'){i++;}
  1662. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1663. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1664. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1665. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1666. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1667. {
  1668. retString.Append(oDate.d.Minute.ToString().PadLeft(i-s, '0'));
  1669. }
  1670. break;
  1671. case 's':// second in minute (Number) 55
  1672. while (i < format.Length && format[i]=='s'){i++;}
  1673. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1674. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1675. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1676. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1677. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1678. {
  1679. retString.Append(oDate.d.Second.ToString().PadLeft(i-s, '0'));
  1680. }
  1681. break;
  1682. case 'S':// millisecond (Number) 978
  1683. while (i < format.Length && format[i]=='S'){i++;}
  1684. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1685. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1686. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1687. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1688. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1689. {
  1690. retString.Append(oDate.d.Millisecond.ToString().PadLeft(i-s, '0'));
  1691. }
  1692. break;
  1693. case 'E':// day in week (Text) Tuesday
  1694. while (i < format.Length && format[i]=='E'){i++;}
  1695. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1696. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1697. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1698. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1699. {
  1700. if (i-s <= 3)
  1701. {
  1702. retString.Append(dayAbbreviation((int)oDate.d.DayOfWeek));
  1703. }
  1704. else
  1705. {
  1706. retString.Append(dayName((int)oDate.d.DayOfWeek));
  1707. }
  1708. }
  1709. break;
  1710. case 'D':// day in year (Number) 189
  1711. while (i < format.Length && format[i]=='D'){i++;}
  1712. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1713. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1714. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1715. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1716. {
  1717. retString.Append(oDate.d.DayOfYear.ToString().PadLeft(i-s, '0'));
  1718. }
  1719. break;
  1720. case 'F':// day of week in month (Number) 2 (2nd Wed in July)
  1721. while (i < format.Length && format[i]=='F'){i++;}
  1722. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1723. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1724. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1725. Object.ReferenceEquals(oDate.GetType(), typeof(MonthDay)) ||
  1726. Object.ReferenceEquals(oDate.GetType(), typeof(Day)) ||
  1727. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1728. {
  1729. retString.Append(dayOfWeekInMonth(oDate.d.Day).ToString().PadLeft(i-s, '0'));
  1730. }
  1731. break;
  1732. case 'w':// week in year (Number) 27
  1733. while (i < format.Length && format[i]=='w'){i++;}
  1734. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1735. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1736. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1737. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1738. {
  1739. retString.Append(weekInYear(oDate.d));
  1740. }
  1741. break;
  1742. case 'W':// week in month (Number) 2
  1743. while (i < format.Length && format[i]=='W'){i++;}
  1744. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1745. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1746. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1747. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1748. {
  1749. retString.Append(weekInMonth(oDate.d));
  1750. }
  1751. break;
  1752. case 'a':// am/pm marker (Text) PM
  1753. while (i < format.Length && format[i]=='a'){i++;}
  1754. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1755. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1756. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1757. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1758. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1759. {
  1760. if (oDate.d.Hour < 12)
  1761. retString.Append("AM");
  1762. else
  1763. retString.Append("PM");
  1764. }
  1765. break;
  1766. case 'k':// hour in day (1~24) (Number) 24
  1767. while (i < format.Length && format[i]=='k'){i++;}
  1768. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1769. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1770. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1771. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1772. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1773. {
  1774. int hour = oDate.d.Hour + 1;
  1775. retString.Append(hour.ToString().PadLeft(i-s, '0'));
  1776. }
  1777. break;
  1778. case 'K':// hour in am/pm (0~11) (Number) 0
  1779. while (i < format.Length && format[i]=='K'){i++;}
  1780. if (Object.ReferenceEquals(oDate.GetType(), typeof(DateTimeTZ)) ||
  1781. Object.ReferenceEquals(oDate.GetType(), typeof(DateTZ)) ||
  1782. Object.ReferenceEquals(oDate.GetType(), typeof(YearMonth)) ||
  1783. Object.ReferenceEquals(oDate.GetType(), typeof(TimeTZ)) ||
  1784. Object.ReferenceEquals(oDate.GetType(), typeof(YearTZ)))
  1785. {
  1786. int hour = oDate.d.Hour % 12;
  1787. retString.Append(hour.ToString().PadLeft(i-s, '0'));
  1788. }
  1789. break;
  1790. case 'z':// time zone (Text) Pacific Standard Time
  1791. while (i < format.Length && format[i]=='z'){i++;}
  1792. //
  1793. // BUGBUG: Need to convert to full timezone names or timezone abbrevs
  1794. // if they are available. Now cheating by using GMT offsets.
  1795. retString.Append(oDate.GetGMTOffsetTimeZone());
  1796. break;
  1797. case 'Z':// rfc 822 time zone
  1798. while (i < format.Length && format[i]=='Z'){i++;}
  1799. retString.Append(oDate.Get822TimeZone());
  1800. break;
  1801. case '\'':// escape for text (Delimiter)
  1802. if (i < format.Length && format[i+1] == '\'')
  1803. {
  1804. i++;
  1805. while (i < format.Length && format[i]=='\''){i++;}
  1806. retString.Append("'");
  1807. }
  1808. else
  1809. {
  1810. i++;
  1811. while (i < format.Length && format[i]!='\'' && i <= format.Length){retString.Append(format.Substring(i++, 1));}
  1812. if (i >= format.Length)return "";
  1813. i++;
  1814. }
  1815. break;
  1816. default:
  1817. retString.Append(format[i]);
  1818. i++;
  1819. break;
  1820. }
  1821. }
  1822. return retString.ToString();
  1823. }
  1824. catch(FormatException)
  1825. {
  1826. return "";
  1827. }
  1828. }
  1829. /// <summary>
  1830. /// This wrapper method will be renamed during custom build
  1831. /// to provide conformant EXSLT function name.
  1832. /// </summary>
  1833. public string formatDate_RENAME_ME(string d, string format)
  1834. {
  1835. return formatDate(d, format);
  1836. }
  1837. /// <summary>
  1838. /// Implements the following function
  1839. /// string date:parse-date(string, string)
  1840. /// BUGBUG: should use Java formatting strings, not Windows.
  1841. /// </summary>
  1842. /// <param name="d">The date to parse</param>
  1843. /// <param name="format">One of the format strings understood by the
  1844. /// DateTime.ToString(string) method.</param>
  1845. /// <returns>The parsed date</returns>
  1846. public string parseDate(string d, string format){
  1847. try{
  1848. DateTime date = DateTime.ParseExact(d, format, CultureInfo.CurrentCulture);
  1849. return XmlConvert.ToString(date, XmlDateTimeSerializationMode.RoundtripKind);
  1850. }catch(FormatException){
  1851. return "";
  1852. }
  1853. }
  1854. /// <summary>
  1855. /// This wrapper method will be renamed during custom build
  1856. /// to provide conformant EXSLT function name.
  1857. /// </summary>
  1858. public string parseDate_RENAME_ME(string d, string format)
  1859. {
  1860. return parseDate(d, format);
  1861. }
  1862. /// <summary>
  1863. /// Implements the following function
  1864. /// string:date:difference(string, string)
  1865. /// </summary>
  1866. /// <param name="start">The start date</param>
  1867. /// <param name="end">The end date</param>
  1868. /// <returns>A positive difference if start is before end otherwise a negative
  1869. /// difference. The difference is in the ISO 8601 date difference format as either
  1870. /// [-]P[yY][mM]
  1871. /// or
  1872. /// [-]P[dD][T][hH][mM][sS]
  1873. /// P means a difference and is required
  1874. /// At least one of Y M D H M S is required
  1875. /// If a higher order component is 0, it is suppressed (for example, if there are 0 years and
  1876. /// 1 month, then Y is suppressed. If there are 1 years and 0 months, M is not suppressed)
  1877. /// If the input format is yyyy-MM or yyyy, then the output is [-]P[yY][mM]
  1878. /// If the input format includes days, hours, minutes or seconds, then the output is
  1879. /// [-]P[dD][T][hH][mM][sS].
  1880. /// If there H M and S are all 0, the T is suppressed.
  1881. /// </returns>
  1882. public string difference(string start, string end)
  1883. {
  1884. try
  1885. {
  1886. ExsltDateTime startdate = ExsltDateTimeFactory.ParseDate(start);
  1887. ExsltDateTime enddate = ExsltDateTimeFactory.ParseDate(end);
  1888. // The rules are pretty tricky. basically, interpret both strings as the least-
  1889. // specific format
  1890. if (Object.ReferenceEquals(startdate.GetType(), typeof(YearTZ)) ||
  1891. Object.ReferenceEquals(enddate.GetType(), typeof(YearTZ)))
  1892. {
  1893. StringBuilder retString = new StringBuilder("");
  1894. int yearDiff = enddate.d.Year - startdate.d.Year;
  1895. if (yearDiff < 0)
  1896. retString.Append('-');
  1897. retString.Append('P');
  1898. retString.Append(Math.Abs(yearDiff));
  1899. retString.Append('Y');
  1900. return retString.ToString();
  1901. }
  1902. else if (Object.ReferenceEquals(startdate.GetType(), typeof(YearMonth)) ||
  1903. Object.ReferenceEquals(enddate.GetType(), typeof(YearMonth)))
  1904. {
  1905. StringBuilder retString = new StringBuilder("");
  1906. int yearDiff = enddate.d.Year - startdate.d.Year;
  1907. int monthDiff = enddate.d.Month - startdate.d.Month;
  1908. // Borrow from the year if necessary
  1909. if ((yearDiff > 0) && (Math.Sign(monthDiff) == -1))
  1910. {
  1911. yearDiff--;
  1912. monthDiff += 12;
  1913. }
  1914. else if ((yearDiff < 0) && (Math.Sign(monthDiff) == 1))
  1915. {
  1916. yearDiff++;
  1917. monthDiff -= 12;
  1918. }
  1919. if ((yearDiff < 0) || ((yearDiff == 0) && (monthDiff < 0)))
  1920. {
  1921. retString.Append('-');
  1922. }
  1923. retString.Append('P');
  1924. if (yearDiff != 0)
  1925. {
  1926. retString.Append(Math.Abs(yearDiff));
  1927. retString.Append('Y');
  1928. }
  1929. retString.Append(Math.Abs(monthDiff));
  1930. retString.Append('M');
  1931. return retString.ToString();
  1932. }
  1933. else
  1934. {
  1935. // Simulate casting to the most truncated format. i.e. if one
  1936. // Arg is DateTZ and the other is DateTimeTZ, get rid of the time
  1937. // for both.
  1938. if (Object.ReferenceEquals(startdate.GetType(), typeof(DateTZ)) ||
  1939. Object.ReferenceEquals(enddate.GetType(), typeof(DateTZ)))
  1940. {
  1941. startdate = new DateTZ(startdate.d.ToString("yyyy-MM-dd"));
  1942. enddate = new DateTZ(enddate.d.ToString("yyyy-MM-dd"));
  1943. }
  1944. TimeSpan ts = enddate.d.Subtract(startdate.d);
  1945. return XmlConvert.ToString(ts);
  1946. }
  1947. }
  1948. catch(FormatException)
  1949. {
  1950. return "";
  1951. }
  1952. }
  1953. /// <summary>
  1954. /// Implements the following function
  1955. /// date:add(string, string)
  1956. /// </summary>
  1957. /// <param name="datetime">An ISO8601 date/time</param>
  1958. /// <param name="duration">the duration to add</param>
  1959. /// <returns>The new time</returns>
  1960. public string add(string datetime, string duration)
  1961. {
  1962. try
  1963. {
  1964. ExsltDateTime date = ExsltDateTimeFactory.ParseDate(datetime);
  1965. //TimeSpan timespan = System.Xml.XmlConvert.ToTimeSpan(duration);
  1966. Regex durationRE = new Regex(
  1967. @"^(-)?" + // May begin with a - sign
  1968. @"P" + // Must contain P as first or 2nd char
  1969. @"(?=\d+|(?:T\d+))" + // Must contain at least one digit after P or after PT
  1970. @"(?:(\d+)Y)?" + // May contain digits plus Y for year
  1971. @"(?:(\d+)M)?" + // May contain digits plus M for month
  1972. @"(?:(\d+)D)?" + // May contain digits plus D for day
  1973. @"(?=T\d+)?" + // If there is a T here, must be digits afterwards
  1974. @"T?" + // May contain a T
  1975. @"(?:(\d+)H)?" + // May contain digits plus H for hours
  1976. @"(?:(\d+)M)?" + // May contain digits plus M for minutes
  1977. @"(?:(\d+)S)?" + // May contain digits plus S for seconds
  1978. @"$",
  1979. RegexOptions.IgnoreCase | RegexOptions.Singleline
  1980. );
  1981. Match m = durationRE.Match(duration);
  1982. int negation = 1, years = 0, months = 0, days = 0,
  1983. hours = 0, minutes = 0, seconds = 0;
  1984. if (m.Success)
  1985. {
  1986. //date.d = date.d.Add(timespan);
  1987. // According to the XML datetime spec at
  1988. // http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes,
  1989. // we need to first add the year/month part, then we can add the
  1990. // day/hour/minute/second part
  1991. if (CultureInfo.InvariantCulture.CompareInfo.Compare(m.Groups[1].Value, "-") == 0)
  1992. negation = -1;
  1993. if (m.Groups[2].Length > 0)
  1994. years = negation * int.Parse(m.Groups[2].Value);
  1995. if (m.Groups[3].Length > 0)
  1996. months = negation * int.Parse(m.Groups[3].Value);
  1997. if (m.Groups[4].Length > 0)
  1998. days = negation * int.Parse(m.Groups[4].Value);
  1999. if (m.Groups[5].Length > 0)
  2000. hours = negation * int.Parse(m.Groups[5].Value);
  2001. if (m.Groups[6].Length > 0)
  2002. minutes = negation * int.Parse(m.Groups[6].Value);
  2003. if (m.Groups[7].Length > 0)
  2004. seconds = negation * int.Parse(m.Groups[7].Value);
  2005. date.d = date.d.AddYears(years);
  2006. date.d = date.d.AddMonths(months);
  2007. date.d = date.d.AddDays(days);
  2008. date.d = date.d.AddHours(hours);
  2009. date.d = date.d.AddMinutes(minutes);
  2010. date.d = date.d.AddSeconds(seconds);
  2011. // we should return the same format as passed in
  2012. // return date.ToString("yyyy-MM-dd\"T\"HH:mm:ss");
  2013. return date.ToString();
  2014. }
  2015. else
  2016. {
  2017. return "";
  2018. }
  2019. }
  2020. catch(FormatException)
  2021. {
  2022. return "";
  2023. }
  2024. }
  2025. /// <summary>
  2026. /// Implements the following function
  2027. /// string:date:add-duration(string, string)
  2028. /// </summary>
  2029. /// <param name="duration1">Initial duration</param>
  2030. /// <param name="duration2">the duration to add</param>
  2031. /// <returns>The new time</returns>
  2032. public string addDuration(string duration1, string duration2)
  2033. {
  2034. try
  2035. {
  2036. TimeSpan timespan1 = XmlConvert.ToTimeSpan(duration1);
  2037. TimeSpan timespan2 = XmlConvert.ToTimeSpan(duration2);
  2038. return XmlConvert.ToString(timespan1.Add(timespan2));
  2039. }
  2040. catch(FormatException)
  2041. {
  2042. return "";
  2043. }
  2044. }
  2045. /// <summary>
  2046. /// This wrapper method will be renamed during custom build
  2047. /// to provide conformant EXSLT function name.
  2048. /// </summary>
  2049. public string addDuration_RENAME_ME(string duration1, string duration2)
  2050. {
  2051. return addDuration(duration1, duration2);
  2052. }
  2053. /// <summary>
  2054. /// Helper method for date:seconds() that takes an ExsltDateTime.
  2055. /// </summary>
  2056. /// <param name="d"></param>
  2057. /// <returns>difference in seconds between the specified date and the
  2058. /// epoch (1970-01-01T00:00:00Z)</returns>
  2059. private double seconds(ExsltDateTime d)
  2060. {
  2061. DateTime epoch = new DateTime(1970, 1, 1, 0,0,0,0, CultureInfo.InvariantCulture.Calendar);
  2062. return d.ToUniversalTime().Subtract(epoch).TotalSeconds;
  2063. }
  2064. /// <summary>
  2065. /// Implements the following function
  2066. /// number date:seconds()
  2067. /// </summary>
  2068. /// <returns>The amount of seconds since the epoch (1970-01-01T00:00:00Z)</returns>
  2069. public double seconds()
  2070. {
  2071. return seconds(new DateTimeTZ());
  2072. }
  2073. /// <summary>
  2074. /// Implements the following function
  2075. /// number date:seconds(string)
  2076. /// </summary>
  2077. /// <returns>If date passed in, the amount of seconds between the specified date and the
  2078. /// epoch (1970-01-01T00:00:00Z). If timespan passed in, returns the number of seconds
  2079. /// in the timespan.</returns>
  2080. public double seconds(string datetime)
  2081. {
  2082. try
  2083. {
  2084. return seconds(ExsltDateTimeFactory.ParseDate(datetime));
  2085. }
  2086. catch(FormatException){ ; } //might be a duration
  2087. try
  2088. {
  2089. TimeSpan duration = XmlConvert.ToTimeSpan(datetime);
  2090. return duration.TotalSeconds;
  2091. }
  2092. catch(FormatException)
  2093. {
  2094. return System.Double.NaN;
  2095. }
  2096. }
  2097. /// <summary>
  2098. /// Implements the following function
  2099. /// string date:sum(node-set)
  2100. /// </summary>
  2101. /// <param name="iterator">Nodeset of timespans</param>
  2102. /// <returns>The sum of the timespans within a node set.</returns>
  2103. public string sum(XPathNodeIterator iterator)
  2104. {
  2105. TimeSpan sum = new TimeSpan(0,0,0,0);
  2106. if(iterator.Count == 0)
  2107. {
  2108. return "";
  2109. }
  2110. try
  2111. {
  2112. while(iterator.MoveNext())
  2113. {
  2114. sum = XmlConvert.ToTimeSpan(iterator.Current.Value).Add(sum);
  2115. }
  2116. }
  2117. catch(FormatException)
  2118. {
  2119. return "";
  2120. }
  2121. return XmlConvert.ToString(sum) ; //XmlConvert.ToString(sum);
  2122. }
  2123. /// <summary>
  2124. /// Implements the following function
  2125. /// string date:duration()
  2126. /// </summary>
  2127. /// <returns>seconds since the beginning of the epoch until now</returns>
  2128. public string duration()
  2129. {
  2130. return duration(seconds());
  2131. }
  2132. /// <summary>
  2133. /// Implements the following function
  2134. /// string date:duration(number)
  2135. /// </summary>
  2136. /// <param name="seconds"></param>
  2137. /// <returns></returns>
  2138. public string duration(double seconds)
  2139. {
  2140. return XmlConvert.ToString(TimeSpan.FromSeconds(seconds));
  2141. }
  2142. }
  2143. }