Date.ecl 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285
  1. /*##############################################################################
  2. ## HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®. All rights reserved.
  3. ############################################################################## */
  4. /* The functions defined in this module are provisional, and subject to change */
  5. IMPORT lib_stringlib.StringLib;
  6. IMPORT lib_timelib.TimeLib;
  7. EXPORT Date := MODULE
  8. // A record structure with the different date elements separated out.
  9. EXPORT Date_rec := RECORD
  10. INTEGER2 year;
  11. UNSIGNED1 month;
  12. UNSIGNED1 day;
  13. END;
  14. // An unsigned number holding a date in the decimal form YYYYMMDD.
  15. // This type doesn't support dates before 1AD.
  16. EXPORT Date_t := UNSIGNED4;
  17. // A number of elapsed days. Origin depends on the function called.
  18. EXPORT Days_t := INTEGER4;
  19. // A record structure with the different time elements separated out.
  20. EXPORT Time_rec := RECORD
  21. UNSIGNED1 hour;
  22. UNSIGNED1 minute;
  23. UNSIGNED1 second;
  24. END;
  25. // An unsigned number holding a time of day in the decimal form HHMMDD.
  26. EXPORT Time_t := UNSIGNED3;
  27. // A signed number holding a number of seconds. Can be used to represent either
  28. // a duration or the number of seconds since epoch (Jan 1, 1970).
  29. EXPORT Seconds_t := INTEGER8;
  30. // A record structure with the different date and time elements separated out.
  31. EXPORT DateTime_rec := RECORD
  32. Date_rec;
  33. Time_Rec;
  34. END;
  35. // A signed number holding a number of microseconds. Can be used to represent
  36. // either a duration or the number of microseconds since epoch (Jan 1, 1970).
  37. EXPORT Timestamp_t := INTEGER8;
  38. /**
  39. * Extracts the year from a date type.
  40. *
  41. * @param date The date.
  42. * @return An integer representing the year.
  43. */
  44. EXPORT INTEGER2 Year(Date_t date) := date DIV 10000;
  45. /**
  46. * Extracts the month from a date type.
  47. *
  48. * @param date The date.
  49. * @return An integer representing the year.
  50. */
  51. EXPORT UNSIGNED1 Month(Date_t date) := (date DIV 100) % 100;
  52. /**
  53. * Extracts the day of the month from a date type.
  54. *
  55. * @param date The date.
  56. * @return An integer representing the year.
  57. */
  58. EXPORT UNSIGNED1 Day(Date_t date) := date % 100;
  59. /**
  60. * Extracts the hour from a time type.
  61. *
  62. * @param time The time.
  63. * @return An integer representing the hour.
  64. */
  65. EXPORT UNSIGNED1 Hour(Time_t time) := time DIV 10000;
  66. /**
  67. * Extracts the minutes from a time type.
  68. *
  69. * @param time The time.
  70. * @return An integer representing the minutes.
  71. */
  72. EXPORT UNSIGNED1 Minute(Time_t time) := (time DIV 100) % 100;
  73. /**
  74. * Extracts the seconds from a time type.
  75. *
  76. * @param time The time.
  77. * @return An integer representing the seconds.
  78. */
  79. EXPORT UNSIGNED1 Second(Time_t time) := time % 100;
  80. /**
  81. * Combines year, month day to create a date type.
  82. *
  83. * @param year The year (0-9999).
  84. * @param month The month (1-12).
  85. * @param day The day (1..daysInMonth).
  86. * @return A date created by combining the fields.
  87. */
  88. EXPORT Date_t DateFromParts(INTEGER2 year, UNSIGNED1 month, UNSIGNED1 day) := (year * 100 + month) * 100 + day;
  89. /**
  90. * Combines hour, minute second to create a time type.
  91. *
  92. * @param hour The hour (0-23).
  93. * @param minute The minute (0-59).
  94. * @param second The second (0-59).
  95. * @return A time created by combining the fields.
  96. */
  97. EXPORT Time_t TimeFromParts(UNSIGNED1 hour, UNSIGNED1 minute, UNSIGNED1 second) := (hour * 100 + minute) * 100 + second;
  98. /**
  99. * Combines date and time components to create a seconds type. The date must
  100. * be represented within the Gregorian calendar after the year 1600.
  101. *
  102. * @param year The year (1601-30827).
  103. * @param month The month (1-12).
  104. * @param day The day (1..daysInMonth).
  105. * @param hour The hour (0-23).
  106. * @param minute The minute (0-59).
  107. * @param second The second (0-59).
  108. * @param is_local_time TRUE if the datetime components are expressed
  109. * in local time rather than UTC, FALSE if the
  110. * components are expressed in UTC. Optional,
  111. * defaults to FALSE.
  112. * @return A Seconds_t value created by combining the fields.
  113. */
  114. EXPORT Seconds_t SecondsFromParts(INTEGER2 year,
  115. UNSIGNED1 month,
  116. UNSIGNED1 day,
  117. UNSIGNED1 hour,
  118. UNSIGNED1 minute,
  119. UNSIGNED1 second,
  120. BOOLEAN is_local_time = FALSE) :=
  121. TimeLib.SecondsFromParts(year, month, day, hour, minute, second, is_local_time);
  122. /**
  123. * Converts the number of seconds since epoch to a structure containing
  124. * date and time parts. The result must be representable within the
  125. * Gregorian calendar after the year 1600.
  126. *
  127. * @param seconds The number of seconds since epoch.
  128. * @return Module with exported attributes for year, month,
  129. * day, hour, minute, second, day_of_week, date
  130. * and time.
  131. */
  132. EXPORT SecondsToParts(Seconds_t seconds) := FUNCTION
  133. parts := ROW(TimeLib.SecondsToParts(seconds));
  134. result := MODULE
  135. EXPORT INTEGER2 year := parts.year + 1900;
  136. EXPORT UNSIGNED1 month := parts.mon + 1;
  137. EXPORT UNSIGNED1 day := parts.mday;
  138. EXPORT UNSIGNED1 hour := parts.hour;
  139. EXPORT UNSIGNED1 minute := parts.min;
  140. EXPORT UNSIGNED1 second := parts.sec;
  141. EXPORT UNSIGNED1 day_of_week := parts.wday + 1;
  142. EXPORT Date_t date := DateFromParts(year,month,day);
  143. EXPORT Time_t time := TimeFromParts(hour,minute,second);
  144. END;
  145. RETURN result;
  146. END;
  147. /**
  148. * Converts the number of microseconds since epoch to the number of seconds
  149. * since epoch.
  150. *
  151. * @param timestamp The number of microseconds since epoch.
  152. * @return The number of seconds since epoch.
  153. */
  154. EXPORT Seconds_t TimestampToSeconds(Timestamp_t timestamp) := timestamp DIV 1000000;
  155. /**
  156. * Tests whether the year is a leap year in the Gregorian calendar.
  157. *
  158. * @param year The year (0-9999).
  159. * @return True if the year is a leap year.
  160. */
  161. EXPORT BOOLEAN IsLeapYear(INTEGER2 year) := (year % 4 = 0) AND ((year % 100 != 0) OR (year % 400 = 0));
  162. /**
  163. * Tests whether a date is a leap year in the Gregorian calendar.
  164. *
  165. * @param date The date.
  166. * @return True if the year is a leap year.
  167. */
  168. EXPORT BOOLEAN IsDateLeapYear(Date_t date) := IsLeapYear(Year(date));
  169. SHARED YearDelta := +4800; // Offset the years by 4800 so dates up to -4713 work
  170. SHARED GregorianDateOrigin := -1753469; // 1 Jan 1AD = 1
  171. /**
  172. * Combines year, month, day in the Gregorian calendar to create the number
  173. * days since 31st December 1BC.
  174. *
  175. * @param year The year (-4713..9999).
  176. * @param month The month (1-12). A missing value (0) is treated as 1.
  177. * @param day The day (1..daysInMonth). A missing value (0) is treated as 1.
  178. * @return The number of elapsed days (1 Jan 1AD = 1)
  179. */
  180. EXPORT Days_t FromGregorianYMD(INTEGER2 year, UNSIGNED1 month, UNSIGNED1 day) := FUNCTION
  181. //See Frequently Asked Questions about Calendars by Claus Toendering
  182. safeDay := MAX(1, day); // treat 0 as 1
  183. safeMonth := MAX(1, month); // treat 0 as 1
  184. a := (14 - safeMonth) DIV 12;
  185. y := year + YearDelta - a;
  186. m := safeMonth + 12*a - 3;
  187. jd := safeDay + (153 * m + 2) DIV 5 + 365 * y + y DIV 4 - y DIV 100 + y DIV 400;
  188. RETURN jd + (GregorianDateOrigin - 1);
  189. END;
  190. /**
  191. * Converts the number days since 31st December 1BC to a date in the Gregorian calendar.
  192. *
  193. * @param days The number of elapsed days (1 Jan 1AD = 1)
  194. * @return Module containing Year, Month, Day in the Gregorian calendar
  195. */
  196. EXPORT ToGregorianYMD(Days_t days) := FUNCTION
  197. // See Fliegel and van Flandern (1968) and other quoted sources
  198. // (e.g., http://www.ortelius.de/kalender/calc_en.php)
  199. // Process as 4, 100 and 400 year cycles.
  200. daysIn4Years := 3*365+366;
  201. daysIn100Years := 25*daysIn4Years-1;
  202. daysIn400Years := 4*daysIn100Years+1;
  203. // Calculate days in each of the cycles.
  204. adjustedDays := days - GregorianDateOrigin;
  205. num400Years := adjustedDays div daysIn400Years;
  206. rem400Years := adjustedDays % daysIn400Years;
  207. num100Years := ((rem400Years div daysIn100Years + 1) * 3) DIV 4;
  208. rem100Years := rem400Years - num100Years * daysIn100Years;
  209. num4Years := rem100Years div daysIn4Years;
  210. rem4Years := rem100Years % daysIn4Years;
  211. years := ((rem4Years div 365 + 1) * 3) DIV 4;
  212. numdays := rem4Years - years * 365;
  213. //Now calculate the actual year, month day
  214. y := num400Years * 400 + num100Years * 100 + num4Years * 4 + years;
  215. m := (numdays * 5 + 308) div 153 - 2;
  216. d := numdays - (m + 4) * 153 div 5 + 122;
  217. result := MODULE
  218. EXPORT year := (y + (m + 2) div 12) - YearDelta;
  219. EXPORT month := (m + 2) % 12 + 1;
  220. EXPORT day := d + 1;
  221. END;
  222. RETURN result;
  223. END;
  224. /**
  225. * Converts a date in the Gregorian calendar to the number days since 31st December 1BC.
  226. *
  227. * @param date The date (using the Gregorian calendar)
  228. * @return The number of elapsed days (1 Jan 1AD = 1)
  229. */
  230. EXPORT Days_t FromGregorianDate(Date_t date) :=
  231. DEFINE FromGregorianYMD(Year(date), Month(date), Day(date));
  232. /**
  233. * Converts the number days since 31st December 1BC to a date in the Gregorian calendar.
  234. *
  235. * @param days The number of elapsed days (1 Jan 1AD = 1)
  236. * @return A Date_t in the Gregorian calendar
  237. */
  238. EXPORT Date_t ToGregorianDate(Days_t days) := DEFINE FUNCTION
  239. date := ToGregorianYMD(days);
  240. RETURN DateFromParts(date.year, date.month, date.day);
  241. END;
  242. /**
  243. * Returns a number representing the day of the year indicated by the given date.
  244. * The date must be in the Gregorian calendar after the year 1600.
  245. *
  246. * @param date A Date_t value.
  247. * @return A number (1-366) representing the number of days since
  248. * the beginning of the year.
  249. */
  250. EXPORT UNSIGNED2 DayOfYear(Date_t date) := FUNCTION
  251. theYear := Year(date);
  252. theMonth := Month(date);
  253. theDay := Day(date);
  254. dayNum := TimeLib.GetDayOfYear(theYear, theMonth, theDay) + 1;
  255. RETURN dayNum;
  256. END;
  257. /**
  258. * Returns a number representing the day of the week indicated by the given date.
  259. * The date must be in the Gregorian calendar after the year 1600.
  260. *
  261. * @param date A Date_t value.
  262. * @return A number 1-7 representing the day of the week, where 1 = Sunday.
  263. */
  264. EXPORT UNSIGNED1 DayOfWeek(Date_t date) := FUNCTION
  265. theYear := Year(date);
  266. theMonth := Month(date);
  267. theDay := Day(date);
  268. dayCode := TimeLib.GetDayOfWeek(theYear, theMonth, theDay) + 1;
  269. RETURN dayCode;
  270. END;
  271. /**
  272. * Tests whether the year is a leap year in the Julian calendar.
  273. *
  274. * @param year The year (0-9999).
  275. * @return True if the year is a leap year.
  276. */
  277. EXPORT BOOLEAN IsJulianLeapYear(INTEGER2 year) := (year % 4 = 0);
  278. SHARED JulianDateOrigin := -1753505; // 1 Jan 1AD = 1
  279. /**
  280. * Combines year, month, day in the Julian calendar to create the number
  281. * days since 31st December 1BC.
  282. *
  283. * @param year The year (-4800..9999).
  284. * @param month The month (1-12).
  285. * @param day The day (1..daysInMonth).
  286. * @return The number of elapsed days (1 Jan 1AD = 1)
  287. */
  288. EXPORT Days_t FromJulianYMD(INTEGER2 year, UNSIGNED1 month, UNSIGNED1 day) := FUNCTION
  289. //See Frequently Asked Questions about Calendars by Claus Toendering
  290. a := (14 - month) DIV 12;
  291. y := year + YearDelta - a;
  292. m := month + 12*a - 3;
  293. jd := day + (153 * m + 2) DIV 5 + 365 * y + y DIV 4;
  294. RETURN jd + (JulianDateOrigin-1);
  295. END;
  296. /**
  297. * Converts the number days since 31st December 1BC to a date in the Julian calendar.
  298. *
  299. * @param days The number of elapsed days (1 Jan 1AD = 1)
  300. * @return Module containing Year, Month, Day in the Julian calendar
  301. */
  302. EXPORT ToJulianYMD(Days_t days) := FUNCTION
  303. //See Frequently Asked Questions about Calendars by Claus Toendering
  304. daysIn4Years := 3*365+366;
  305. c := days - JulianDateOrigin;
  306. d := (4 * c + 3) DIV daysIn4Years;
  307. e := c - ((daysIn4Years * d) DIV 4);
  308. m := (5 * e + 2) DIV 153;
  309. result := MODULE
  310. EXPORT UNSIGNED1 day := e - ((153 * m + 2) DIV 5) + 1;
  311. EXPORT UNSIGNED1 month := m + 3 - 12 * (m DIV 10);
  312. EXPORT INTEGER2 year := d - YearDelta + (m DIV 10);
  313. END;
  314. RETURN result;
  315. END;
  316. /**
  317. * Converts a date in the Julian calendar to the number days since 31st December 1BC.
  318. *
  319. * @param date The date (using the Julian calendar)
  320. * @return The number of elapsed days (1 Jan 1AD = 1)
  321. */
  322. EXPORT Days_t FromJulianDate(Date_t date) := DEFINE FromJulianYMD(Year(date), Month(date), Day(date));
  323. /**
  324. * Converts the number days since 31st December 1BC to a date in the Julian calendar.
  325. *
  326. * @param days The number of elapsed days (1 Jan 1AD = 1)
  327. * @return A Date_t in the Julian calendar
  328. */
  329. EXPORT Date_t ToJulianDate(Days_t days) := DEFINE FUNCTION
  330. date := ToJulianYMD(days);
  331. RETURN DateFromParts(date.year, date.month, date.day);
  332. END;
  333. SHARED Date1900Delta := 693596; // 1 Jan 1900 = 0
  334. /**
  335. * Returns the number of days since 1st January 1900 (using the Gregorian Calendar)
  336. *
  337. * @param year The year (-4713..9999).
  338. * @param month The month (1-12). A missing value (0) is treated as 1.
  339. * @param day The day (1..daysInMonth). A missing value (0) is treated as 1.
  340. * @return The number of elapsed days since 1st January 1900
  341. */
  342. EXPORT Days_t DaysSince1900(INTEGER2 year, UNSIGNED1 month, UNSIGNED1 day) :=
  343. FromGregorianYMD(year, month, day) - Date1900Delta;
  344. /**
  345. * Returns the number of days since 1st January 1900 (using the Gregorian Calendar)
  346. *
  347. * @param date The date
  348. * @return The number of elapsed days since 1st January 1900
  349. */
  350. EXPORT Days_t ToDaysSince1900(Date_t date) := DaysSince1900(Year(date),Month(date),Day(date));
  351. /**
  352. * Converts the number days since 1st January 1900 to a date in the Julian calendar.
  353. *
  354. * @param days The number of elapsed days since 1st Jan 1900
  355. * @return A Date_t in the Julian calendar
  356. */
  357. EXPORT Date_t FromDaysSince1900(Days_t days) := ToGregorianDate(days + Date1900Delta);
  358. /**
  359. * Calculate the number of whole years between two dates.
  360. *
  361. * @param from The first date
  362. * @param to The last date
  363. * @return The number of years between them.
  364. */
  365. EXPORT INTEGER YearsBetween (Date_t from, Date_t to) := FUNCTION
  366. fromDate := MIN(from, to);
  367. toDate := MAX(from, to);
  368. years := Year(toDate) - Year(fromDate);
  369. adjustedYears := years - IF(Month(fromDate) > Month(toDate) OR (Month(fromDate) = Month(toDate) AND Day(fromDate) > Day(toDate)), 1, 0);
  370. RETURN adjustedYears * IF(from > to, -1, 1);
  371. END;
  372. /**
  373. * Calculate the number of whole months between two dates.
  374. *
  375. * @param from The first date
  376. * @param to The last date
  377. * @return The number of months between them.
  378. */
  379. EXPORT INTEGER MonthsBetween(Date_t from, Date_t to) := FUNCTION
  380. fromDate := MIN(from, to);
  381. toDate := MAX(from, to);
  382. years := Year(toDate) - Year(fromDate);
  383. months := Month(toDate) - Month(fromDate);
  384. result := years * 12 + months;
  385. adjustedResult := result - IF(Day(fromDate) > Day(toDate), 1, 0);
  386. RETURN adjustedResult * IF(from > to, -1, 1);
  387. END;
  388. /**
  389. * Calculate the number of days between two dates.
  390. *
  391. * @param from The first date
  392. * @param to The last date
  393. * @return The number of days between them.
  394. */
  395. EXPORT INTEGER DaysBetween(Date_t from, Date_t to) := FUNCTION
  396. fromDays := FromGregorianDate(from);
  397. toDays := FromGregorianDate(to);
  398. RETURN toDays - fromDays;
  399. END;
  400. /**
  401. * Combines the fields from a Date_rec to create a Date_t
  402. *
  403. * @param date The row containing the date.
  404. * @return A Date_t representing the combined values.
  405. */
  406. EXPORT Date_t DateFromDateRec(Date_rec date) := (date.year * 100 + date.month) * 100 + date.day;
  407. /**
  408. * Combines the fields from a Date_rec to create a Date_t
  409. *
  410. * @param date The row containing the date.
  411. * @return A Date_t representing the combined values.
  412. */
  413. EXPORT Date_t DateFromRec(Date_rec date) := DateFromDateRec(date) : DEPRECATED('Replaced with DateFromDateRec() function');
  414. /**
  415. * Combines the fields from a Time_rec to create a Time_t
  416. *
  417. * @param time The row containing the time.
  418. * @return A Time_t representing the combined values.
  419. */
  420. EXPORT Time_t TimeFromTimeRec(Time_rec time) := (time.hour * 100 + time.minute) * 100 + time.second;
  421. /**
  422. * Combines the date fields from a DateTime_rec to create a Date_t
  423. *
  424. * @param datetime The row containing the datetime.
  425. * @return A Date_t representing the combined values.
  426. */
  427. EXPORT Date_t DateFromDateTimeRec(DateTime_rec datetime) := (datetime.year * 100 + datetime.month) * 100 + datetime.day;
  428. /**
  429. * Combines the time fields from a DateTime_rec to create a Time_t
  430. *
  431. * @param datetime The row containing the datetime.
  432. * @return A Time_t representing the combined values.
  433. */
  434. EXPORT Time_t TimeFromDateTimeRec(DateTime_rec datetime) := (datetime.hour * 100 + datetime.minute) * 100 + datetime.second;
  435. /**
  436. * Combines the date and time fields from a DateTime_rec to create a Seconds_t
  437. *
  438. * @param datetime The row containing the datetime.
  439. * @param is_local_time TRUE if the datetime components are expressed in local
  440. * time rather than UTC, FALSE if the components are
  441. * expressed in UTC. Optional, defaults to FALSE.
  442. * @return A Seconds_t representing the combined values.
  443. */
  444. EXPORT Seconds_t SecondsFromDateTimeRec(DateTime_rec datetime, BOOLEAN is_local_time = FALSE) :=
  445. SecondsFromParts(datetime.year, datetime.month, datetime.day, datetime.hour, datetime.minute, datetime.second, is_local_time);
  446. /**
  447. * Converts a string to a Date_t using the relevant string format. The resulting
  448. * date must be representable within the Gregorian calendar after the year 1600.
  449. *
  450. * @param date_text The string to be converted.
  451. * @param format The format of the input string.
  452. * (See documentation for strftime)
  453. * @return The date that was matched in the string. Returns 0 if failed to match
  454. * or if the date components match but the result is an invalid date.
  455. *
  456. * Supported characters:
  457. %B Full month name
  458. %b or %h Abbreviated month name
  459. %d Day of month (two digits)
  460. %e Day of month (two digits, or a space followed by a single digit)
  461. %m Month (two digits)
  462. %t Whitespace
  463. %y year within century (00-99)
  464. %Y Full year (yyyy)
  465. %j Julian day (1-366)
  466. Common date formats
  467. American '%m/%d/%Y' mm/dd/yyyy
  468. Euro '%d/%m/%Y' dd/mm/yyyy
  469. Iso format '%Y-%m-%d' yyyy-mm-dd
  470. Iso basic '%Y%m%d' yyyymmdd
  471. '%d-%b-%Y' dd-mon-yyyy e.g., '21-Mar-1954'
  472. */
  473. EXPORT Date_t FromStringToDate(STRING date_text, VARSTRING format) :=
  474. StringLib.StringToDate(date_text, format);
  475. /**
  476. * Converts a string to a date using the relevant string format.
  477. *
  478. * @param date_text The string to be converted.
  479. * @param format The format of the input string.
  480. * (See documentation for strftime)
  481. * @return The date that was matched in the string.
  482. * Returns 0 if failed to match.
  483. */
  484. EXPORT Date_t FromString(STRING date_text, VARSTRING format) :=
  485. FromStringToDate(date_text, format) : DEPRECATED('Replaced with FromStringToDate() function');
  486. /**
  487. * Converts a string to a Time_t using the relevant string format.
  488. *
  489. * @param date_text The string to be converted.
  490. * @param format The format of the input string.
  491. * (See documentation for strftime)
  492. * @return The time that was matched in the string. Returns 0 if failed to match.
  493. *
  494. * Supported characters:
  495. %H Hour (two digits)
  496. %k (two digits, or a space followed by a single digit)
  497. %M Minute (two digits)
  498. %S Second (two digits)
  499. %t Whitespace
  500. */
  501. EXPORT Time_t FromStringToTime(STRING time_text, VARSTRING format) :=
  502. StringLib.StringToTimeOfDay(time_text, format);
  503. /**
  504. * Matches a string against a set of date string formats and returns a valid
  505. * Date_t object from the first format that successfully parses the string.
  506. *
  507. * @param date_text The string to be converted.
  508. * @param formats A set of formats to check against the string.
  509. * (See documentation for strftime)
  510. * @return The date that was matched in the string.
  511. * Returns 0 if failed to match.
  512. */
  513. EXPORT Date_t MatchDateString(STRING date_text, SET OF VARSTRING formats) :=
  514. StringLib.MatchDate(date_text, formats);
  515. /**
  516. * Matches a string against a set of time string formats and returns a valid
  517. * Time_t object from the first format that successfully parses the string.
  518. *
  519. * @param time_text The string to be converted.
  520. * @param formats A set of formats to check against the string.
  521. * (See documentation for strftime)
  522. * @return The time that was matched in the string.
  523. * Returns 0 if failed to match.
  524. */
  525. EXPORT Time_t MatchTimeString(STRING time_text, SET OF VARSTRING formats) :=
  526. StringLib.MatchTimeOfDay(time_text, formats);
  527. /**
  528. * Formats a date as a string.
  529. *
  530. * @param date The date to be converted.
  531. * @param format The format template to use for the conversion;
  532. * see strftime() for appropriate values. The maximum
  533. * length of the resulting string is 255 characters.
  534. * Optional; defaults to '%Y-%m-%d' which is YYYY-MM-DD.
  535. * @return Blank if date cannot be formatted, or the date in the
  536. * requested format.
  537. */
  538. EXPORT STRING DateToString(Date_t date, VARSTRING format = '%Y-%m-%d') :=
  539. TimeLib.DateToString(date, format);
  540. /**
  541. * Formats a time as a string.
  542. *
  543. * @param time The time to be converted.
  544. * @param format The format template to use for the conversion;
  545. * see strftime() for appropriate values. The maximum
  546. * length of the resulting string is 255 characters.
  547. * Optional; defaults to '%H:%M:%S' which is HH:MM:SS.
  548. * @return Blank if the time cannot be formatted, or the time
  549. * in the requested format.
  550. */
  551. EXPORT STRING TimeToString(Time_t time, VARSTRING format = '%H:%M:%S') :=
  552. TimeLib.TimeToString(time, format);
  553. /**
  554. * Converts a Seconds_t value into a human-readable string using a format template.
  555. *
  556. * @param seconds The seconds since epoch.
  557. * @param format The format template to use for the conversion; see
  558. * strftime() for appropriate values. The maximum length
  559. * of the resulting string is 255 characters.
  560. * Optional; defaults to '%Y-%m-%dT%H:%M:%S' which is YYYY-MM-DDTHH:MM:SS.
  561. * @return The converted seconds as a string.
  562. */
  563. EXPORT STRING SecondsToString(Seconds_t seconds, VARSTRING format = '%Y-%m-%dT%H:%M:%S') :=
  564. TimeLib.SecondsToString(seconds, format);
  565. /**
  566. * Formats a date as a string.
  567. *
  568. * @param date The date to be converted.
  569. * @param format The format the date is output in.
  570. * (See documentation for strftime)
  571. * @return Blank if date cannot be formatted, or the date in the
  572. * requested format.
  573. */
  574. EXPORT STRING ToString(Date_t date, VARSTRING format) := DateToString(date, format) : DEPRECATED('Replaced with DateToString() function');
  575. /**
  576. * Converts a date from one format to another
  577. *
  578. * @param date_text The string containing the date to be converted.
  579. * @param from_format The format the date is to be converted from.
  580. * @param to_format The format the date is to be converted to.
  581. * @return The converted string, or blank if it failed to match the format.
  582. */
  583. EXPORT STRING ConvertDateFormat(STRING date_text, VARSTRING from_format='%m/%d/%Y', VARSTRING to_format='%Y%m%d') :=
  584. DateToString(FromStringToDate(date_text, from_format), to_format);
  585. /**
  586. * Converts a date from one format to another
  587. *
  588. * @param date_text The string containing the date to be converted.
  589. * @param from_format The format the date is to be converted from.
  590. * @param to_format The format the date is to be converted to.
  591. * @return The converted string, or blank if it failed to match the format.
  592. */
  593. EXPORT STRING ConvertFormat(STRING date_text, VARSTRING from_format='%m/%d/%Y', VARSTRING to_format='%Y%m%d') :=
  594. ConvertDateFormat(date_text, from_format, to_format) : DEPRECATED('Replaced with ConvertDateFormat() function');
  595. /**
  596. * Converts a time from one format to another
  597. *
  598. * @param time_text The string containing the time to be converted.
  599. * @param from_format The format the time is to be converted from.
  600. * @param to_format The format the time is to be converted to.
  601. * @return The converted string, or blank if it failed to match the format.
  602. */
  603. EXPORT STRING ConvertTimeFormat(STRING time_text, VARSTRING from_format='%H%M%S', VARSTRING to_format='%H:%M:%S') :=
  604. TimeToString(FromStringToTime(time_text, from_format), to_format);
  605. /**
  606. * Converts a date that matches one of a set of formats to another.
  607. *
  608. * @param date_text The string containing the date to be converted.
  609. * @param from_formats The list of formats the date is to be converted from.
  610. * @param to_format The format the date is to be converted to.
  611. * @return The converted string, or blank if it failed to match the format.
  612. */
  613. EXPORT STRING ConvertDateFormatMultiple(STRING date_text, SET OF VARSTRING from_formats, VARSTRING to_format='%Y%m%d') := FUNCTION
  614. matchResult := MatchDateString(date_text, from_formats);
  615. reformatResult := IF(matchResult = (Date_t)0, '', DateToString(matchResult, to_format));
  616. RETURN reformatResult;
  617. END;
  618. /**
  619. * Converts a date that matches one of a set of formats to another.
  620. *
  621. * @param date_text The string containing the date to be converted.
  622. * @param from_formats The list of formats the date is to be converted from.
  623. * @param to_format The format the date is to be converted to.
  624. * @return The converted string, or blank if it failed to match the format.
  625. */
  626. EXPORT STRING ConvertFormatMultiple(STRING date_text, SET OF VARSTRING from_formats, VARSTRING to_format='%Y%m%d') :=
  627. ConvertDateFormatMultiple(date_text, from_formats, to_format) : DEPRECATED('Replaced with ConvertDateFormatMultiple() function');
  628. /**
  629. * Converts a time that matches one of a set of formats to another.
  630. *
  631. * @param time_text The string containing the time to be converted.
  632. * @param from_formats The list of formats the time is to be converted from.
  633. * @param to_format The format the time is to be converted to.
  634. * @return The converted string, or blank if it failed to match the format.
  635. */
  636. EXPORT STRING ConvertTimeFormatMultiple(STRING time_text, SET OF VARSTRING from_formats, VARSTRING to_format='%H:%m:%s') :=
  637. TimeToString(MatchTimeString(time_text, from_formats), to_format);
  638. /**
  639. * Adjusts a date by incrementing or decrementing year, month and/or day values.
  640. * The date must be in the Gregorian calendar after the year 1600.
  641. * If the new calculated date is invalid then it will be normalized according
  642. * to mktime() rules. Example: 20140130 + 1 month = 20140302.
  643. *
  644. * @param date The date to adjust.
  645. * @param year_delta The requested change to the year value;
  646. * optional, defaults to zero.
  647. * @param month_delta The requested change to the month value;
  648. * optional, defaults to zero.
  649. * @param day_delta The requested change to the day of month value;
  650. * optional, defaults to zero.
  651. * @return The adjusted Date_t value.
  652. */
  653. EXPORT Date_t AdjustDate(Date_t date,
  654. INTEGER2 year_delta = 0,
  655. INTEGER4 month_delta = 0,
  656. INTEGER4 day_delta = 0) :=
  657. TimeLib.AdjustDate(date, year_delta, month_delta, day_delta);
  658. /**
  659. * Adjusts a date by adding or subtracting seconds. The date must be in the
  660. * Gregorian calendar after the year 1600. If the new calculated
  661. * date is invalid then it will be normalized according to mktime() rules.
  662. * Example: 20140130 + 172800 seconds = 20140201.
  663. *
  664. * @param date The date to adjust.
  665. * @param seconds_delta The requested change to the date, in seconds.
  666. * @return The adjusted Date_t value.
  667. */
  668. EXPORT Date_t AdjustDateBySeconds(Date_t date, INTEGER4 seconds_delta) :=
  669. TimeLib.AdjustDateBySeconds(date, seconds_delta);
  670. /**
  671. * Adjusts a time by incrementing or decrementing hour, minute and/or second
  672. * values. If the new calculated time is invalid then it will be normalized
  673. * according to mktime() rules.
  674. *
  675. * @param time The time to adjust.
  676. * @param hour_delta The requested change to the hour value;
  677. * optional, defaults to zero.
  678. * @param minute_delta The requested change to the minute value;
  679. * optional, defaults to zero.
  680. * @param second_delta The requested change to the second of month value;
  681. * optional, defaults to zero.
  682. * @return The adjusted Time_t value.
  683. */
  684. EXPORT Time_t AdjustTime(Time_t time,
  685. INTEGER2 hour_delta = 0,
  686. INTEGER4 minute_delta = 0,
  687. INTEGER4 second_delta = 0) :=
  688. TimeLib.AdjustTime(time, hour_delta, minute_delta, second_delta);
  689. /**
  690. * Adjusts a time by adding or subtracting seconds. If the new calculated
  691. * time is invalid then it will be normalized according to mktime() rules.
  692. *
  693. * @param time The time to adjust.
  694. * @param seconds_delta The requested change to the time, in seconds.
  695. * @return The adjusted Time_t value.
  696. */
  697. EXPORT Time_t AdjustTimeBySeconds(Time_t time, INTEGER4 seconds_delta) :=
  698. TimeLib.AdjustTimeBySeconds(time, seconds_delta);
  699. /**
  700. * Adjusts a Seconds_t value by adding or subtracting years, months, days,
  701. * hours, minutes and/or seconds. This is performed by first converting the
  702. * seconds into a full date/time structure, applying any delta values to
  703. * individual date/time components, then converting the structure back to the
  704. * number of seconds. This interim date must lie within Gregorian calendar
  705. * after the year 1600. If the interim structure is found to have an invalid
  706. * date/time then it will be normalized according to mktime() rules. Therefore,
  707. * some delta values (such as "1 month") are actually relative to the value of
  708. * the seconds argument.
  709. *
  710. * @param seconds The number of seconds to adjust.
  711. * @param year_delta The requested change to the year value;
  712. * optional, defaults to zero.
  713. * @param month_delta The requested change to the month value;
  714. * optional, defaults to zero.
  715. * @param day_delta The requested change to the day of month value;
  716. * optional, defaults to zero.
  717. * @param hour_delta The requested change to the hour value;
  718. * optional, defaults to zero.
  719. * @param minute_delta The requested change to the minute value;
  720. * optional, defaults to zero.
  721. * @param second_delta The requested change to the second of month value;
  722. * optional, defaults to zero.
  723. * @return The adjusted Seconds_t value.
  724. */
  725. EXPORT Seconds_t AdjustSeconds(Seconds_t seconds,
  726. INTEGER2 year_delta = 0,
  727. INTEGER4 month_delta = 0,
  728. INTEGER4 day_delta = 0,
  729. INTEGER4 hour_delta = 0,
  730. INTEGER4 minute_delta = 0,
  731. INTEGER4 second_delta = 0) :=
  732. TimeLib.AdjustSeconds(seconds, year_delta, month_delta, day_delta, hour_delta, minute_delta, second_delta);
  733. /**
  734. * Adjusts a date by incrementing or decrementing months and/or years. This
  735. * routine uses the rule outlined in McGinn v. State, 46 Neb. 427, 65 N.W. 46 (1895):
  736. * "The term calendar month, whether employed in statutes or contracts, and
  737. * not appearing to have been used in a different sense, denotes a period
  738. * terminating with the day of the succeeding month numerically corresponding
  739. * to the day of its beginning, less one. If there be no corresponding day of
  740. * the succeeding month, it terminates with the last day thereof." The
  741. * internet suggests similar legal positions exist in the Commonwealth
  742. * and Germany. Note that day adjustments are performed after year and month
  743. * adjustments using the preceding rules. As an example, Jan. 31, 2014 + 1 month
  744. * will result in Feb. 28, 2014; Jan. 31, 2014 + 1 month + 1 day will result
  745. * in Mar. 1, 2014.
  746. *
  747. * @param date The date to adjust, in the Gregorian calendar after 1600.
  748. * @param year_delta The requested change to the year value;
  749. * optional, defaults to zero.
  750. * @param month_delta The requested change to the month value;
  751. * optional, defaults to zero.
  752. * @param day_delta The requested change to the day value;
  753. * optional, defaults to zero.
  754. * @return The adjusted Date_t value.
  755. */
  756. EXPORT Date_t AdjustCalendar(Date_t date,
  757. INTEGER2 year_delta = 0,
  758. INTEGER4 month_delta = 0,
  759. INTEGER4 day_delta = 0) :=
  760. TimeLib.AdjustCalendar(date, year_delta, month_delta, day_delta);
  761. /**
  762. * Returns a boolean indicating whether daylight savings time is currently
  763. * in effect locally.
  764. *
  765. * @return TRUE if daylight savings time is currently in effect, FALSE otherwise.
  766. */
  767. EXPORT BOOLEAN IsLocalDaylightSavingsInEffect() :=
  768. TimeLib.IsLocalDaylightSavingsInEffect();
  769. /**
  770. * Returns the offset (in seconds) of the time represented from UTC, with
  771. * positive values indicating locations east of the Prime Meridian. Given a
  772. * UTC time in seconds since epoch, you can find the local time by adding the
  773. * result of this function to the seconds.
  774. *
  775. * @return The number of seconds offset from UTC.
  776. */
  777. EXPORT INTEGER4 LocalTimeZoneOffset() :=
  778. TimeLib.LocalTimeZoneOffset();
  779. /**
  780. * Returns the current date.
  781. *
  782. * @param in_local_time TRUE if the returned value should be local to the
  783. * cluster computing the date, FALSE for UTC.
  784. * Optional, defaults to FALSE.
  785. * @return A Date_t representing the current date.
  786. */
  787. EXPORT Date_t CurrentDate(BOOLEAN in_local_time = FALSE) :=
  788. TimeLib.CurrentDate(in_local_time);
  789. /**
  790. * Returns the current date in the local time zone.
  791. *
  792. * @return A Date_t representing the current date.
  793. */
  794. EXPORT Date_t Today() := CurrentDate(TRUE);
  795. /**
  796. * Returns the current time of day
  797. *
  798. * @param in_local_time TRUE if the returned value should be local to the
  799. * cluster computing the time, FALSE for UTC.
  800. * Optional, defaults to FALSE.
  801. * @return A Time_t representing the current time of day.
  802. */
  803. EXPORT Time_t CurrentTime(BOOLEAN in_local_time = FALSE) :=
  804. TimeLib.CurrentTime(in_local_time);
  805. /**
  806. * Returns the current date and time as the number of seconds since epoch.
  807. *
  808. * @param in_local_time TRUE if the returned value should be local to the
  809. * cluster computing the time, FALSE for UTC.
  810. * Optional, defaults to FALSE.
  811. * @return A Seconds_t representing the current time in
  812. * UTC or local time, depending on the argument.
  813. */
  814. EXPORT Seconds_t CurrentSeconds(BOOLEAN in_local_time = FALSE) :=
  815. TimeLib.CurrentSeconds(in_local_time);
  816. /**
  817. * Returns the current date and time as the number of microseconds since epoch.
  818. *
  819. * @param in_local_time TRUE if the returned value should be local to the
  820. * cluster computing the time, FALSE for UTC.
  821. * Optional, defaults to FALSE.
  822. * @return A Timestamp_t representing the current time in
  823. * microseconds in UTC or local time, depending on
  824. * the argument.
  825. */
  826. EXPORT Timestamp_t CurrentTimestamp(BOOLEAN in_local_time = FALSE) :=
  827. TimeLib.CurrentTimestamp(in_local_time);
  828. /**
  829. * Returns the beginning and ending dates for the month surrounding the given date.
  830. *
  831. * @param as_of_date The reference date from which the month will be
  832. * calculated. This date must be a date within the
  833. * Gregorian calendar. Optional, defaults to the
  834. * current date in UTC.
  835. * @return Module with exported attributes for startDate and endDate.
  836. */
  837. EXPORT DatesForMonth(Date_t as_of_date = CurrentDate(FALSE)) := FUNCTION
  838. lastDay := TimeLib.GetLastDayOfMonth(as_of_date);
  839. firstDay := (lastDay DIV 100) * 100 + 1;
  840. result := MODULE
  841. EXPORT Date_t startDate := firstDay;
  842. EXPORT Date_t endDate := lastDay;
  843. END;
  844. RETURN result;
  845. END;
  846. /**
  847. * Returns the beginning and ending dates for the week surrounding the given date
  848. * (Sunday marks the beginning of a week).
  849. *
  850. * @param as_of_date The reference date from which the week will be
  851. * calculated. This date must be a date within the
  852. * Gregorian calendar. Optional, defaults to the
  853. * current date in UTC.
  854. * @return Module with exported attributes for startDate and endDate.
  855. */
  856. EXPORT DatesForWeek(Date_t as_of_date = CurrentDate(FALSE)) := FUNCTION
  857. lastWeekDates := ROW(TimeLib.DatesForWeek(as_of_date));
  858. result := MODULE
  859. EXPORT Date_t startDate := lastWeekDates.startDate;
  860. EXPORT Date_t endDate := lastWeekDates.endDate;
  861. END;
  862. RETURN result;
  863. END;
  864. /**
  865. * Tests whether a date is valid, both by range-checking the year and by
  866. * validating each of the other individual components.
  867. *
  868. * @param date The date to validate.
  869. * @param yearLowerBound The minimum acceptable year.
  870. * Optional; defaults to 1800.
  871. * @param yearUpperBound The maximum acceptable year.
  872. * Optional; defaults to 2100.
  873. * @return TRUE if the date is valid, FALSE otherwise.
  874. */
  875. EXPORT BOOLEAN IsValidDate(Date_t date,
  876. INTEGER2 yearLowerBound = 1800,
  877. INTEGER2 yearUpperBound = 2100) := FUNCTION
  878. yearInBounds := (Year(date) BETWEEN yearLowerBound AND yearUpperBound);
  879. monthInBounds := (Month(date) BETWEEN 1 AND 12);
  880. maxDayInMonth := CHOOSE(Month(date),31,IF(IsLeapYear(Year(date)),29,28),31,30,31,30,31,31,30,31,30,31);
  881. dayInBounds := (Day(date) BETWEEN 1 AND maxDayInMonth);
  882. RETURN yearInBounds AND monthInBounds AND dayInBounds;
  883. END;
  884. /**
  885. * Tests whether a date is valid in the Gregorian calendar. The year
  886. * must be between 1601 and 30827.
  887. *
  888. * @param date The Date_t to validate.
  889. * @return TRUE if the date is valid, FALSE otherwise.
  890. */
  891. EXPORT BOOLEAN IsValidGregorianDate(Date_t date) := FUNCTION
  892. yearInBounds := (Year(date) BETWEEN 1601 AND 30827);
  893. matchesNormalized := (date = AdjustDate(date)); // AdjustDate normalizes, so this is a validation check
  894. RETURN yearInBounds AND matchesNormalized;
  895. END;
  896. /**
  897. * Tests whether a time is valid.
  898. *
  899. * @param time The time to validate.
  900. * @return TRUE if the time is valid, FALSE otherwise.
  901. */
  902. EXPORT BOOLEAN IsValidTime(Time_t time) := FUNCTION
  903. hourInBounds := (Hour(time) BETWEEN 0 AND 23);
  904. minuteInBounds := (Minute(time) BETWEEN 0 AND 59);
  905. secondInBounds := (Second(time) BETWEEN 0 AND 59);
  906. RETURN hourInBounds AND minuteInBounds AND secondInBounds;
  907. END;
  908. //------------------------------------------------------------------------------
  909. // Transforms
  910. //------------------------------------------------------------------------------
  911. /**
  912. * A transform to create a Date_rec from the individual elements
  913. *
  914. * @param year The year
  915. * @param month The month (1-12).
  916. * @param day The day (1..daysInMonth).
  917. * @return A transform that creates a Date_rec containing the date.
  918. */
  919. EXPORT Date_rec CreateDate(INTEGER2 year, UNSIGNED1 month, UNSIGNED1 day) := TRANSFORM
  920. SELF.year := year;
  921. SELF.month := month;
  922. SELF.day := day;
  923. END;
  924. /**
  925. * A transform to create a Date_rec from a Seconds_t value.
  926. *
  927. * @param seconds The number seconds since epoch.
  928. * @return A transform that creates a Date_rec containing the date.
  929. */
  930. EXPORT Date_rec CreateDateFromSeconds(Seconds_t seconds) := TRANSFORM
  931. timeParts := SecondsToParts(seconds);
  932. SELF.year := timeParts.year;
  933. SELF.month := timeParts.month;
  934. SELF.day := timeParts.day;
  935. END;
  936. /**
  937. * A transform to create a Time_rec from the individual elements
  938. *
  939. * @param hour The hour (0-23).
  940. * @param minute The minute (0-59).
  941. * @param second The second (0-59).
  942. * @return A transform that creates a Time_rec containing the time of day.
  943. */
  944. EXPORT Time_rec CreateTime(UNSIGNED1 hour, UNSIGNED1 minute, UNSIGNED1 second) := TRANSFORM
  945. SELF.hour := hour;
  946. SELF.minute := minute;
  947. SELF.second := second;
  948. END;
  949. /**
  950. * A transform to create a Time_rec from a Seconds_t value.
  951. *
  952. * @param seconds The number seconds since epoch.
  953. * @return A transform that creates a Time_rec containing the time of day.
  954. */
  955. EXPORT Time_rec CreateTimeFromSeconds(Seconds_t seconds) := TRANSFORM
  956. timeParts := SecondsToParts(seconds);
  957. SELF.hour := timeParts.hour;
  958. SELF.minute := timeParts.minute;
  959. SELF.second := timeParts.second;
  960. END;
  961. /**
  962. * A transform to create a DateTime_rec from the individual elements
  963. *
  964. * @param year The year
  965. * @param month The month (1-12).
  966. * @param day The day (1..daysInMonth).
  967. * @param hour The hour (0-23).
  968. * @param minute The minute (0-59).
  969. * @param second The second (0-59).
  970. * @return A transform that creates a DateTime_rec containing date
  971. * and time components.
  972. */
  973. EXPORT DateTime_rec CreateDateTime(INTEGER2 year,
  974. UNSIGNED1 month,
  975. UNSIGNED1 day,
  976. UNSIGNED1 hour,
  977. UNSIGNED1 minute,
  978. UNSIGNED1 second) := TRANSFORM
  979. SELF.year := year;
  980. SELF.month := month;
  981. SELF.day := day;
  982. SELF.hour := hour;
  983. SELF.minute := minute;
  984. SELF.second := second;
  985. END;
  986. /**
  987. * A transform to create a DateTime_rec from a Seconds_t value.
  988. *
  989. * @param seconds The number seconds since epoch.
  990. * @return A transform that creates a DateTime_rec containing
  991. * date and time components.
  992. */
  993. EXPORT DateTime_rec CreateDateTimeFromSeconds(Seconds_t seconds) := TRANSFORM
  994. timeParts := SecondsToParts(seconds);
  995. SELF.year := timeParts.year;
  996. SELF.month := timeParts.month;
  997. SELF.day := timeParts.day;
  998. SELF.hour := timeParts.hour;
  999. SELF.minute := timeParts.minute;
  1000. SELF.second := timeParts.second;
  1001. END;
  1002. END; // Module