dateutil.inc 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437
  1. {$mode objfpc}
  2. {$h+}
  3. {
  4. This file is part of the Free Pascal run time library.
  5. Copyright (c) 1999-2000 by the Free Pascal development team
  6. Delphi/Kylix compatibility unit, provides Date/Time handling routines.
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. unit dateutils;
  14. interface
  15. {$ifndef FPUNONE}
  16. uses
  17. SysUtils, Math, Types;
  18. { ---------------------------------------------------------------------
  19. Various constants
  20. ---------------------------------------------------------------------}
  21. const
  22. DaysPerWeek = 7;
  23. WeeksPerFortnight = 2;
  24. MonthsPerYear = 12;
  25. YearsPerDecade = 10;
  26. YearsPerCentury = 100;
  27. YearsPerMillennium = 1000;
  28. // ISO day numbers.
  29. DayMonday = 1;
  30. DayTuesday = 2;
  31. DayWednesday = 3;
  32. DayThursday = 4;
  33. DayFriday = 5;
  34. DaySaturday = 6;
  35. DaySunday = 7;
  36. // Fraction of a day
  37. OneHour = 1/HoursPerDay;
  38. OneMinute = 1/MinsPerDay;
  39. OneSecond = 1/SecsPerDay;
  40. OneMillisecond = 1/MSecsPerDay;
  41. { This is actual days per year but you need to know if it's a leap year}
  42. DaysPerYear: array [Boolean] of Word = (365, 366);
  43. { Used in RecodeDate, RecodeTime and RecodeDateTime for those datetime }
  44. { fields you want to leave alone }
  45. RecodeLeaveFieldAsIs = High(Word);
  46. { ---------------------------------------------------------------------
  47. Global variables used in this unit
  48. ---------------------------------------------------------------------}
  49. Const
  50. { Average over a 4 year span. Valid for next 100 years }
  51. ApproxDaysPerMonth: Double = 30.4375;
  52. ApproxDaysPerYear: Double = 365.25;
  53. { ---------------------------------------------------------------------
  54. Simple trimming functions.
  55. ---------------------------------------------------------------------}
  56. Function DateOf(const AValue: TDateTime): TDateTime;
  57. Function TimeOf(const AValue: TDateTime): TDateTime;
  58. { ---------------------------------------------------------------------
  59. Identification functions.
  60. ---------------------------------------------------------------------}
  61. Function IsInLeapYear(const AValue: TDateTime): Boolean;
  62. Function IsPM(const AValue: TDateTime): Boolean;
  63. Function IsValidDate(const AYear, AMonth, ADay: Word): Boolean;
  64. Function IsValidTime(const AHour, AMinute, ASecond, AMilliSecond: Word): Boolean;
  65. Function IsValidDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word): Boolean;
  66. Function IsValidDateDay(const AYear, ADayOfYear: Word): Boolean;
  67. Function IsValidDateWeek(const AYear, AWeekOfYear, ADayOfWeek: Word): Boolean;
  68. Function IsValidDateMonthWeek(const AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word): Boolean;
  69. { ---------------------------------------------------------------------
  70. Enumeration functions.
  71. ---------------------------------------------------------------------}
  72. Function WeeksInYear(const AValue: TDateTime): Word;
  73. Function WeeksInAYear(const AYear: Word): Word;
  74. Function DaysInYear(const AValue: TDateTime): Word;
  75. Function DaysInAYear(const AYear: Word): Word;
  76. Function DaysInMonth(const AValue: TDateTime): Word;
  77. Function DaysInAMonth(const AYear, AMonth: Word): Word;
  78. { ---------------------------------------------------------------------
  79. Variations on current date/time.
  80. ---------------------------------------------------------------------}
  81. Function Today: TDateTime;
  82. Function Yesterday: TDateTime;
  83. Function Tomorrow: TDateTime;
  84. Function IsToday(const AValue: TDateTime): Boolean;
  85. Function IsSameDay(const AValue, ABasis: TDateTime): Boolean;
  86. Function PreviousDayOfWeek (DayOfWeek : Word) : Word;
  87. { ---------------------------------------------------------------------
  88. Extraction functions.
  89. ---------------------------------------------------------------------}
  90. Function YearOf(const AValue: TDateTime): Word;
  91. Function MonthOf(const AValue: TDateTime): Word;
  92. Function WeekOf(const AValue: TDateTime): Word;
  93. Function DayOf(const AValue: TDateTime): Word;
  94. Function HourOf(const AValue: TDateTime): Word;
  95. Function MinuteOf(const AValue: TDateTime): Word;
  96. Function SecondOf(const AValue: TDateTime): Word;
  97. Function MilliSecondOf(const AValue: TDateTime): Word;
  98. { ---------------------------------------------------------------------
  99. Start/End of year functions.
  100. ---------------------------------------------------------------------}
  101. Function StartOfTheYear(const AValue: TDateTime): TDateTime;
  102. Function EndOfTheYear(const AValue: TDateTime): TDateTime;
  103. Function StartOfAYear(const AYear: Word): TDateTime;
  104. Function EndOfAYear(const AYear: Word): TDateTime;
  105. { ---------------------------------------------------------------------
  106. Start/End of month functions.
  107. ---------------------------------------------------------------------}
  108. Function StartOfTheMonth(const AValue: TDateTime): TDateTime;
  109. Function EndOfTheMonth(const AValue: TDateTime): TDateTime;
  110. Function StartOfAMonth(const AYear, AMonth: Word): TDateTime;
  111. Function EndOfAMonth(const AYear, AMonth: Word): TDateTime;
  112. { ---------------------------------------------------------------------
  113. Start/End of week functions.
  114. ---------------------------------------------------------------------}
  115. Function StartOfTheWeek(const AValue: TDateTime): TDateTime;
  116. Function EndOfTheWeek(const AValue: TDateTime): TDateTime;
  117. Function StartOfAWeek(const AYear, AWeekOfYear: Word; const ADayOfWeek: Word): TDateTime;
  118. Function StartOfAWeek(const AYear, AWeekOfYear: Word): TDateTime; // ADayOFWeek 1
  119. Function EndOfAWeek(const AYear, AWeekOfYear: Word; const ADayOfWeek: Word): TDateTime;
  120. Function EndOfAWeek(const AYear, AWeekOfYear: Word): TDateTime; // const ADayOfWeek: Word = 7
  121. { ---------------------------------------------------------------------
  122. Start/End of day functions.
  123. ---------------------------------------------------------------------}
  124. Function StartOfTheDay(const AValue: TDateTime): TDateTime;
  125. Function EndOfTheDay(const AValue: TDateTime): TDateTime;
  126. Function StartOfADay(const AYear, AMonth, ADay: Word): TDateTime; overload;
  127. Function StartOfADay(const AYear, ADayOfYear: Word): TDateTime; overload;
  128. Function EndOfADay(const AYear, AMonth, ADay: Word): TDateTime; overload;
  129. Function EndOfADay(const AYear, ADayOfYear: Word): TDateTime; overload;
  130. { ---------------------------------------------------------------------
  131. Part of year functions.
  132. ---------------------------------------------------------------------}
  133. Function MonthOfTheYear(const AValue: TDateTime): Word;
  134. Function WeekOfTheYear(const AValue: TDateTime): Word; overload;
  135. Function WeekOfTheYear(const AValue: TDateTime; var AYear: Word): Word; overload;
  136. Function DayOfTheYear(const AValue: TDateTime): Word;
  137. Function HourOfTheYear(const AValue: TDateTime): Word;
  138. Function MinuteOfTheYear(const AValue: TDateTime): LongWord;
  139. Function SecondOfTheYear(const AValue: TDateTime): LongWord;
  140. Function MilliSecondOfTheYear(const AValue: TDateTime): Int64;
  141. { ---------------------------------------------------------------------
  142. Part of month functions.
  143. ---------------------------------------------------------------------}
  144. Function WeekOfTheMonth(const AValue: TDateTime): Word; overload;
  145. Function WeekOfTheMonth(const AValue: TDateTime; var AYear, AMonth: Word): Word; overload;
  146. Function DayOfTheMonth(const AValue: TDateTime): Word;
  147. Function HourOfTheMonth(const AValue: TDateTime): Word;
  148. Function MinuteOfTheMonth(const AValue: TDateTime): Word;
  149. Function SecondOfTheMonth(const AValue: TDateTime): LongWord;
  150. Function MilliSecondOfTheMonth(const AValue: TDateTime): LongWord;
  151. { ---------------------------------------------------------------------
  152. Part of week functions.
  153. ---------------------------------------------------------------------}
  154. Function DayOfTheWeek(const AValue: TDateTime): Word;
  155. Function HourOfTheWeek(const AValue: TDateTime): Word;
  156. Function MinuteOfTheWeek(const AValue: TDateTime): Word;
  157. Function SecondOfTheWeek(const AValue: TDateTime): LongWord;
  158. Function MilliSecondOfTheWeek(const AValue: TDateTime): LongWord;
  159. { ---------------------------------------------------------------------
  160. Part of day functions.
  161. ---------------------------------------------------------------------}
  162. Function HourOfTheDay(const AValue: TDateTime): Word;
  163. Function MinuteOfTheDay(const AValue: TDateTime): Word;
  164. Function SecondOfTheDay(const AValue: TDateTime): LongWord;
  165. Function MilliSecondOfTheDay(const AValue: TDateTime): LongWord;
  166. { ---------------------------------------------------------------------
  167. Part of hour functions.
  168. ---------------------------------------------------------------------}
  169. Function MinuteOfTheHour(const AValue: TDateTime): Word;
  170. Function SecondOfTheHour(const AValue: TDateTime): Word;
  171. Function MilliSecondOfTheHour(const AValue: TDateTime): LongWord;
  172. { ---------------------------------------------------------------------
  173. Part of minute functions.
  174. ---------------------------------------------------------------------}
  175. Function SecondOfTheMinute(const AValue: TDateTime): Word;
  176. Function MilliSecondOfTheMinute(const AValue: TDateTime): LongWord;
  177. { ---------------------------------------------------------------------
  178. Part of second functions.
  179. ---------------------------------------------------------------------}
  180. Function MilliSecondOfTheSecond(const AValue: TDateTime): Word;
  181. { ---------------------------------------------------------------------
  182. Range checking functions.
  183. ---------------------------------------------------------------------}
  184. Function WithinPastYears(const ANow, AThen: TDateTime; const AYears: Integer): Boolean;
  185. Function WithinPastMonths(const ANow, AThen: TDateTime; const AMonths: Integer): Boolean;
  186. Function WithinPastWeeks(const ANow, AThen: TDateTime; const AWeeks: Integer): Boolean;
  187. Function WithinPastDays(const ANow, AThen: TDateTime; const ADays: Integer): Boolean;
  188. Function WithinPastHours(const ANow, AThen: TDateTime; const AHours: Int64): Boolean;
  189. Function WithinPastMinutes(const ANow, AThen: TDateTime; const AMinutes: Int64): Boolean;
  190. Function WithinPastSeconds(const ANow, AThen: TDateTime; const ASeconds: Int64): Boolean;
  191. Function WithinPastMilliSeconds(const ANow, AThen: TDateTime; const AMilliSeconds: Int64): Boolean;
  192. { ---------------------------------------------------------------------
  193. Period functions.
  194. ---------------------------------------------------------------------}
  195. Function YearsBetween(const ANow, AThen: TDateTime): Integer;
  196. Function MonthsBetween(const ANow, AThen: TDateTime): Integer;
  197. Function WeeksBetween(const ANow, AThen: TDateTime): Integer;
  198. Function DaysBetween(const ANow, AThen: TDateTime): Integer;
  199. Function HoursBetween(const ANow, AThen: TDateTime): Int64;
  200. Function MinutesBetween(const ANow, AThen: TDateTime): Int64;
  201. Function SecondsBetween(const ANow, AThen: TDateTime): Int64;
  202. Function MilliSecondsBetween(const ANow, AThen: TDateTime): Int64;
  203. { ---------------------------------------------------------------------
  204. Timespan in xxx functions.
  205. ---------------------------------------------------------------------}
  206. { YearSpan and MonthSpan are approximate values }
  207. Function YearSpan(const ANow, AThen: TDateTime): Double;
  208. Function MonthSpan(const ANow, AThen: TDateTime): Double;
  209. Function WeekSpan(const ANow, AThen: TDateTime): Double;
  210. Function DaySpan(const ANow, AThen: TDateTime): Double;
  211. Function HourSpan(const ANow, AThen: TDateTime): Double;
  212. Function MinuteSpan(const ANow, AThen: TDateTime): Double;
  213. Function SecondSpan(const ANow, AThen: TDateTime): Double;
  214. Function MilliSecondSpan(const ANow, AThen: TDateTime): Double;
  215. { ---------------------------------------------------------------------
  216. Increment/decrement functions.
  217. ---------------------------------------------------------------------}
  218. Function IncYear(const AValue: TDateTime; const ANumberOfYears: Integer ): TDateTime;
  219. Function IncYear(const AValue: TDateTime): TDateTime; // ; const ANumberOfYears: Integer = 1)
  220. // Function IncMonth is in SysUtils
  221. Function IncWeek(const AValue: TDateTime; const ANumberOfWeeks: Integer): TDateTime;
  222. Function IncWeek(const AValue: TDateTime): TDateTime; // ; const ANumberOfWeeks: Integer = 1)
  223. Function IncDay(const AValue: TDateTime; const ANumberOfDays: Integer): TDateTime;
  224. Function IncDay(const AValue: TDateTime): TDateTime; //; const ANumberOfDays: Integer = 1)
  225. Function IncHour(const AValue: TDateTime; const ANumberOfHours: Int64): TDateTime;
  226. Function IncHour(const AValue: TDateTime): TDateTime; //; const ANumberOfHours: Int64 = 1
  227. Function IncMinute(const AValue: TDateTime; const ANumberOfMinutes: Int64): TDateTime;
  228. Function IncMinute(const AValue: TDateTime): TDateTime; // ; const ANumberOfMinutes: Int64 = 1
  229. Function IncSecond(const AValue: TDateTime; const ANumberOfSeconds: Int64): TDateTime;
  230. Function IncSecond(const AValue: TDateTime): TDateTime; // ; const ANumberOfSeconds: Int64 = 1
  231. Function IncMilliSecond(const AValue: TDateTime; const ANumberOfMilliSeconds: Int64): TDateTime;
  232. Function IncMilliSecond(const AValue: TDateTime): TDateTime; // ; const ANumberOfMilliSeconds: Int64 = 1
  233. { ---------------------------------------------------------------------
  234. Encode/Decode of complete timestamp
  235. ---------------------------------------------------------------------}
  236. Function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word): TDateTime;
  237. Procedure DecodeDateTime(const AValue: TDateTime; var AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word);
  238. Function TryEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word; var AValue: TDateTime): Boolean;
  239. { ---------------------------------------------------------------------
  240. Encode/decode date, specifying week of year and day of week
  241. ---------------------------------------------------------------------}
  242. Function EncodeDateWeek(const AYear, AWeekOfYear: Word; const ADayOfWeek: Word): TDateTime;
  243. Function EncodeDateWeek(const AYear, AWeekOfYear: Word): TDateTime; //; const ADayOfWeek: Word = 1
  244. Procedure DecodeDateWeek(const AValue: TDateTime; var AYear, AWeekOfYear, ADayOfWeek: Word);
  245. Function TryEncodeDateWeek(const AYear, AWeekOfYear: Word; var AValue: TDateTime; const ADayOfWeek: Word): Boolean;
  246. Function TryEncodeDateWeek(const AYear, AWeekOfYear: Word; var AValue: TDateTime): Boolean; //; const ADayOfWeek: Word = 1
  247. { ---------------------------------------------------------------------
  248. Encode/decode date, specifying day of year
  249. ---------------------------------------------------------------------}
  250. Function EncodeDateDay(const AYear, ADayOfYear: Word): TDateTime;
  251. Procedure DecodeDateDay(const AValue: TDateTime; var AYear, ADayOfYear: Word);
  252. Function TryEncodeDateDay(const AYear, ADayOfYear: Word; var AValue: TDateTime): Boolean;
  253. { ---------------------------------------------------------------------
  254. Encode/decode date, specifying week of month
  255. ---------------------------------------------------------------------}
  256. Function EncodeDateMonthWeek(const AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word): TDateTime;
  257. Procedure DecodeDateMonthWeek(const AValue: TDateTime; var AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word);
  258. Function TryEncodeDateMonthWeek(const AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word; var AValue: TDateTime): Boolean;
  259. { ---------------------------------------------------------------------
  260. Replace given element with supplied value.
  261. ---------------------------------------------------------------------}
  262. Function RecodeYear(const AValue: TDateTime; const AYear: Word): TDateTime;
  263. Function RecodeMonth(const AValue: TDateTime; const AMonth: Word): TDateTime;
  264. Function RecodeDay(const AValue: TDateTime; const ADay: Word): TDateTime;
  265. Function RecodeHour(const AValue: TDateTime; const AHour: Word): TDateTime;
  266. Function RecodeMinute(const AValue: TDateTime; const AMinute: Word): TDateTime;
  267. Function RecodeSecond(const AValue: TDateTime; const ASecond: Word): TDateTime;
  268. Function RecodeMilliSecond(const AValue: TDateTime; const AMilliSecond: Word): TDateTime;
  269. Function RecodeDate(const AValue: TDateTime; const AYear, AMonth, ADay: Word): TDateTime;
  270. Function RecodeTime(const AValue: TDateTime; const AHour, AMinute, ASecond, AMilliSecond: Word): TDateTime;
  271. Function RecodeDateTime(const AValue: TDateTime; const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word): TDateTime;
  272. Function TryRecodeDateTime(const AValue: TDateTime; const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word; var AResult: TDateTime): Boolean;
  273. { ---------------------------------------------------------------------
  274. Comparision of date/time
  275. ---------------------------------------------------------------------}
  276. Function CompareDateTime(const A, B: TDateTime): TValueRelationship;
  277. Function CompareDate(const A, B: TDateTime): TValueRelationship;
  278. Function CompareTime(const A, B: TDateTime): TValueRelationship;
  279. Function SameDateTime(const A, B: TDateTime): Boolean;
  280. Function SameDate(const A, B: TDateTime): Boolean;
  281. Function SameTime(const A, B: TDateTime): Boolean;
  282. { For a given date these Functions tell you the which day of the week of the
  283. month (or year). If its a Thursday, they will tell you if its the first,
  284. second, etc Thursday of the month (or year). Remember, even though its
  285. the first Thursday of the year it doesn't mean its the first week of the
  286. year. See ISO 8601 above for more information. }
  287. Function NthDayOfWeek(const AValue: TDateTime): Word;
  288. Procedure DecodeDayOfWeekInMonth(const AValue: TDateTime; var AYear, AMonth, ANthDayOfWeek, ADayOfWeek: Word);
  289. Function EncodeDayOfWeekInMonth(const AYear, AMonth, ANthDayOfWeek, ADayOfWeek: Word): TDateTime;
  290. Function TryEncodeDayOfWeekInMonth(const AYear, AMonth, ANthDayOfWeek, ADayOfWeek: Word; var AValue: TDateTime): Boolean;
  291. { ---------------------------------------------------------------------
  292. Exception throwing routines
  293. ---------------------------------------------------------------------}
  294. Procedure InvalidDateTimeError(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word; const ABaseDate: TDateTime);
  295. Procedure InvalidDateTimeError(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word); // const ABaseDate: TDateTime = 0
  296. Procedure InvalidDateWeekError(const AYear, AWeekOfYear, ADayOfWeek: Word);
  297. Procedure InvalidDateDayError(const AYear, ADayOfYear: Word);
  298. Procedure InvalidDateMonthWeekError(const AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word);
  299. Procedure InvalidDayOfWeekInMonthError(const AYear, AMonth, ANthDayOfWeek, ADayOfWeek: Word);
  300. { ---------------------------------------------------------------------
  301. Julian and Modified Julian Date conversion support
  302. ---------------------------------------------------------------------}
  303. Function DateTimeToJulianDate(const AValue: TDateTime): Double;
  304. Function JulianDateToDateTime(const AValue: Double): TDateTime;
  305. Function TryJulianDateToDateTime(const AValue: Double; var ADateTime: TDateTime): Boolean;
  306. Function DateTimeToModifiedJulianDate(const AValue: TDateTime): Double;
  307. Function ModifiedJulianDateToDateTime(const AValue: Double): TDateTime;
  308. Function TryModifiedJulianDateToDateTime(const AValue: Double; var ADateTime: TDateTime): Boolean;
  309. { ---------------------------------------------------------------------
  310. Unix timestamp support.
  311. ---------------------------------------------------------------------}
  312. Function DateTimeToUnix(const AValue: TDateTime): Int64;
  313. Function UnixToDateTime(const AValue: Int64): TDateTime;
  314. Function UnixTimeStampToMac(const AValue: Int64): Int64;
  315. { ---------------------------------------------------------------------
  316. Mac timestamp support.
  317. ---------------------------------------------------------------------}
  318. Function DateTimeToMac(const AValue: TDateTime): Int64;
  319. Function MacToDateTime(const AValue: Int64): TDateTime;
  320. Function MacTimeStampToUnix(const AValue: Int64): Int64;
  321. { .....................................................................
  322. Dos <-> Delphi datetime support
  323. .....................................................................}
  324. Function DateTimeToDosDateTime(const AValue: TDateTime): longint;
  325. Function DosDateTimeToDateTime( AValue: longint): TDateTime;
  326. { ScanDateTime is a limited inverse of formatdatetime }
  327. function ScanDateTime(const Pattern:string;const s:string;const fmt:TFormatSettings;startpos:integer=1) : tdatetime; overload;
  328. function ScanDateTime(const Pattern:string;const s:string;startpos:integer=1) : tdatetime; overload;
  329. implementation
  330. uses sysconst;
  331. { ---------------------------------------------------------------------
  332. Auxiliary routines
  333. ---------------------------------------------------------------------}
  334. Procedure NotYetImplemented (FN : String);
  335. begin
  336. Raise Exception.CreateFmt('Function "%s" (dateutils) is not yet implemented',[FN]);
  337. end;
  338. { ---------------------------------------------------------------------
  339. Simple trimming functions.
  340. ---------------------------------------------------------------------}
  341. Function DateOf(const AValue: TDateTime): TDateTime;
  342. begin
  343. Result:=Trunc(AValue);
  344. end;
  345. Function TimeOf(const AValue: TDateTime): TDateTime;
  346. begin
  347. Result:=Frac(Avalue);
  348. end;
  349. { ---------------------------------------------------------------------
  350. Identification functions.
  351. ---------------------------------------------------------------------}
  352. Function IsInLeapYear(const AValue: TDateTime): Boolean;
  353. Var
  354. D,Y,M : Word;
  355. begin
  356. DecodeDate(AValue,Y,M,D);
  357. Result:=IsLeapYear(Y);
  358. end;
  359. Function IsPM(const AValue: TDateTime): Boolean;
  360. Var
  361. H,M,S,MS : Word;
  362. begin
  363. DecodeTime(AValue,H,M,S,MS);
  364. Result:=(H>=12);
  365. end;
  366. Function IsValidDate(const AYear, AMonth, ADay: Word): Boolean;
  367. begin
  368. Result:=(AYear<>0) and (AYear<10000)
  369. and (AMonth in [1..12])
  370. and (ADay<>0) and (ADay<=MonthDays[IsleapYear(AYear),AMonth]);
  371. end;
  372. Function IsValidTime(const AHour, AMinute, ASecond, AMilliSecond: Word): Boolean;
  373. begin
  374. Result:=(AHour=HoursPerDay) and (AMinute=0) and (ASecond=0) and (AMillisecond=0);
  375. Result:=Result or
  376. ((AHour<HoursPerDay) and (AMinute<MinsPerHour) and (ASecond<SecsPerMin) and
  377. (AMillisecond<MSecsPerSec));
  378. end;
  379. Function IsValidDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word): Boolean;
  380. begin
  381. Result:=IsValidDate(AYear,AMonth,ADay) and
  382. IsValidTime(AHour,AMinute,ASecond,AMillisecond)
  383. end;
  384. Function IsValidDateDay(const AYear, ADayOfYear: Word): Boolean;
  385. begin
  386. Result:=(AYear<>0) and (ADayOfYear<>0) and (AYear<10000) and
  387. (ADayOfYear<=DaysPerYear[IsLeapYear(AYear)]);
  388. end;
  389. Function IsValidDateWeek(const AYear, AWeekOfYear, ADayOfWeek: Word): Boolean;
  390. begin
  391. Result:=(AYear<>0) and (AYear<10000)
  392. and (ADayOfWeek in [1..7])
  393. and (AWeekOfYear<>0)
  394. and (AWeekOfYear<=WeeksInaYear(AYear));
  395. { should we not also check whether the day of the week is not
  396. larger than the last day of the last week in the year 9999 ?? }
  397. end;
  398. Function IsValidDateMonthWeek(const AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word): Boolean;
  399. begin
  400. Result:=(AYear<>0) and (AYear<10000)
  401. and (AMonth in [1..12])
  402. and (AWeekOfMonth in [1..5])
  403. and (ADayOfWeek in [1..7]);
  404. end;
  405. { ---------------------------------------------------------------------
  406. Enumeration functions.
  407. ---------------------------------------------------------------------}
  408. Function WeeksInYear(const AValue: TDateTime): Word;
  409. Var
  410. Y,M,D : Word;
  411. begin
  412. DecodeDate(AValue,Y,M,D);
  413. Result:=WeeksInAYear(Y);
  414. end;
  415. Function WeeksInAYear(const AYear: Word): Word;
  416. Var
  417. DOW : Word;
  418. begin
  419. Result:=52;
  420. DOW:=DayOfTheWeek(StartOfAYear(AYear));
  421. If (DOW=4) or ((DOW=3) and IsLeapYear(AYear)) then
  422. Inc(Result);
  423. end;
  424. Function DaysInYear(const AValue: TDateTime): Word;
  425. Var
  426. Y,M,D : Word;
  427. begin
  428. DecodeDate(AValue,Y,M,D);
  429. Result:=DaysPerYear[IsLeapYear(Y)];
  430. end;
  431. Function DaysInAYear(const AYear: Word): Word;
  432. begin
  433. Result:=DaysPerYear[Isleapyear(AYear)];
  434. end;
  435. Function DaysInMonth(const AValue: TDateTime): Word;
  436. Var
  437. Y,M,D : Word;
  438. begin
  439. Decodedate(AValue,Y,M,D);
  440. Result:=MonthDays[IsLeapYear(Y),M];
  441. end;
  442. Function DaysInAMonth(const AYear, AMonth: Word): Word;
  443. begin
  444. Result:=MonthDays[IsLeapYear(AYear),AMonth];
  445. end;
  446. { ---------------------------------------------------------------------
  447. Variations on current date/time.
  448. ---------------------------------------------------------------------}
  449. Function Today: TDateTime;
  450. begin
  451. Result:=Date;
  452. end;
  453. Function Yesterday: TDateTime;
  454. begin
  455. Result:=Date-1;
  456. end;
  457. Function Tomorrow: TDateTime;
  458. begin
  459. Result:=Date+1;
  460. end;
  461. Function IsToday(const AValue: TDateTime): Boolean;
  462. begin
  463. Result:=IsSameDay(AValue,Date);
  464. end;
  465. Function IsSameDay(const AValue, ABasis: TDateTime): Boolean;
  466. Var
  467. D : TDateTime;
  468. begin
  469. D:=AValue-Trunc(ABasis);
  470. Result:=(D>=0) and (D<1);
  471. end;
  472. const
  473. DOWMap: array [1..7] of Word = (7, 1, 2, 3, 4, 5, 6);
  474. Function PreviousDayOfWeek (DayOfWeek : Word) : Word;
  475. begin
  476. If Not (DayOfWeek in [1..7]) then
  477. Raise EConvertError.CreateFmt(SErrInvalidDayOfWeek,[DayOfWeek]);
  478. Result:=DOWMap[DayOfWeek];
  479. end;
  480. { ---------------------------------------------------------------------
  481. Extraction functions.
  482. ---------------------------------------------------------------------}
  483. Function YearOf(const AValue: TDateTime): Word;
  484. Var
  485. D,M : Word;
  486. begin
  487. DecodeDate(AValue,Result,D,M);
  488. end;
  489. Function MonthOf(const AValue: TDateTime): Word;
  490. Var
  491. Y,D : Word;
  492. begin
  493. DecodeDate(AValue,Y,Result,D);
  494. end;
  495. Function WeekOf(const AValue: TDateTime): Word;
  496. begin
  497. Result:=WeekOfTheYear(AValue);
  498. end;
  499. Function DayOf(const AValue: TDateTime): Word;
  500. Var
  501. Y,M : Word;
  502. begin
  503. DecodeDate(AValue,Y,M,Result);
  504. end;
  505. Function HourOf(const AValue: TDateTime): Word;
  506. Var
  507. N,S,MS : Word;
  508. begin
  509. DecodeTime(AValue,Result,N,S,MS);
  510. end;
  511. Function MinuteOf(const AValue: TDateTime): Word;
  512. Var
  513. H,S,MS : Word;
  514. begin
  515. DecodeTime(AValue,H,Result,S,MS);
  516. end;
  517. Function SecondOf(const AValue: TDateTime): Word;
  518. Var
  519. H,N,MS : Word;
  520. begin
  521. DecodeTime(AVAlue,H,N,Result,MS);
  522. end;
  523. Function MilliSecondOf(const AValue: TDateTime): Word;
  524. Var
  525. H,N,S : Word;
  526. begin
  527. DecodeTime(AValue,H,N,S,Result);
  528. end;
  529. { ---------------------------------------------------------------------
  530. Start/End of year functions.
  531. ---------------------------------------------------------------------}
  532. Function StartOfTheYear(const AValue: TDateTime): TDateTime;
  533. Var
  534. Y,M,D : Word;
  535. begin
  536. DecodeDate(AValue,Y,M,D);
  537. Result:=EncodeDate(Y,1,1);
  538. end;
  539. Function EndOfTheYear(const AValue: TDateTime): TDateTime;
  540. Var
  541. Y,M,D : Word;
  542. begin
  543. DecodeDate(AValue,Y,M,D);
  544. Result:=EncodeDateTime(Y,12,31,23,59,59,999);
  545. end;
  546. Function StartOfAYear(const AYear: Word): TDateTime;
  547. begin
  548. Result:=EncodeDate(AYear,1,1);
  549. end;
  550. Function EndOfAYear(const AYear: Word): TDateTime;
  551. begin
  552. Result:=(EncodeDateTime(AYear,12,31,23,59,59,999));
  553. end;
  554. { ---------------------------------------------------------------------
  555. Start/End of month functions.
  556. ---------------------------------------------------------------------}
  557. Function StartOfTheMonth(const AValue: TDateTime): TDateTime;
  558. Var
  559. Y,M,D : Word;
  560. begin
  561. DecodeDate(AValue,Y,M,D);
  562. Result:=EncodeDate(Y,M,1);
  563. // MonthDays[IsLeapYear(Y),M])
  564. end;
  565. Function EndOfTheMonth(const AValue: TDateTime): TDateTime;
  566. Var
  567. Y,M,D : Word;
  568. begin
  569. DecodeDate(AValue,Y,M,D);
  570. Result:=EncodeDateTime(Y,M,MonthDays[IsLeapYear(Y),M],23,59,59,999);
  571. end;
  572. Function StartOfAMonth(const AYear, AMonth: Word): TDateTime;
  573. begin
  574. Result:=EncodeDate(AYear,AMonth,1);
  575. end;
  576. Function EndOfAMonth(const AYear, AMonth: Word): TDateTime;
  577. begin
  578. Result:=EncodeDateTime(AYear,AMonth,MonthDays[IsLeapYear(AYear),AMonth],23,59,59,999);
  579. end;
  580. { ---------------------------------------------------------------------
  581. Start/End of week functions.
  582. ---------------------------------------------------------------------}
  583. Function StartOfTheWeek(const AValue: TDateTime): TDateTime;
  584. begin
  585. Result:=Trunc(AValue)-DayOfTheWeek(AValue)+1;
  586. end;
  587. Function EndOfTheWeek(const AValue: TDateTime): TDateTime;
  588. begin
  589. Result:=EndOfTheDay(AValue-DayOfTheWeek(AValue)+7);
  590. end;
  591. Function StartOfAWeek(const AYear, AWeekOfYear: Word; const ADayOfWeek: Word): TDateTime;
  592. begin
  593. Result:=EncodeDateWeek(AYear,AWeekOfYear,ADayOfWeek);
  594. end;
  595. Function StartOfAWeek(const AYear, AWeekOfYear: Word): TDateTime; // ADayOFWeek 1
  596. begin
  597. Result:=StartOfAWeek(AYear,AWeekOfYear,1)
  598. end;
  599. Function EndOfAWeek(const AYear, AWeekOfYear: Word; const ADayOfWeek: Word): TDateTime;
  600. begin
  601. Result := EndOfTheDay(EncodeDateWeek(AYear, AWeekOfYear, ADayOfWeek));
  602. end;
  603. Function EndOfAWeek(const AYear, AWeekOfYear: Word): TDateTime; // const ADayOfWeek: Word = 7
  604. begin
  605. Result:=EndOfAWeek(AYear,AWeekOfYear,7);
  606. end;
  607. { ---------------------------------------------------------------------
  608. Start/End of day functions.
  609. ---------------------------------------------------------------------}
  610. Function StartOfTheDay(const AValue: TDateTime): TDateTime;
  611. begin
  612. StartOfTheDay:=Trunc(Avalue);
  613. end;
  614. Function EndOfTheDay(const AValue: TDateTime): TDateTime;
  615. Var
  616. Y,M,D : Word;
  617. begin
  618. DecodeDate(AValue,Y,M,D);
  619. Result:=EncodeDateTime(Y,M,D,23,59,59,999);
  620. end;
  621. Function StartOfADay(const AYear, AMonth, ADay: Word): TDateTime;
  622. begin
  623. Result:=EncodeDate(AYear,AMonth,ADay);
  624. end;
  625. Function StartOfADay(const AYear, ADayOfYear: Word): TDateTime;
  626. begin
  627. Result:=StartOfAYear(AYear)+ADayOfYear-1;
  628. end;
  629. Function EndOfADay(const AYear, AMonth, ADay: Word): TDateTime;
  630. begin
  631. Result:=EndOfTheDay(EncodeDate(AYear,AMonth,ADay));
  632. end;
  633. Function EndOfADay(const AYear, ADayOfYear: Word): TDateTime;
  634. begin
  635. Result:=StartOfAYear(AYear)+ADayOfYear-1+EncodeTime(23,59,59,999);
  636. end;
  637. { ---------------------------------------------------------------------
  638. Part of year functions.
  639. ---------------------------------------------------------------------}
  640. Function MonthOfTheYear(const AValue: TDateTime): Word;
  641. Var
  642. Y,D : Word;
  643. begin
  644. DecodeDate(AValue,Y,Result,D);
  645. end;
  646. Function WeekOfTheYear(const AValue: TDateTime): Word;
  647. Var
  648. Y,DOW : Word;
  649. begin
  650. DecodeDateWeek(AValue,Y,Result,DOW)
  651. end;
  652. Function WeekOfTheYear(const AValue: TDateTime; var AYear: Word): Word;
  653. Var
  654. DOW : Word;
  655. begin
  656. DecodeDateWeek(AValue,AYear,Result,DOW);
  657. end;
  658. Function DayOfTheYear(const AValue: TDateTime): Word;
  659. begin
  660. Result:=Trunc(AValue-StartOfTheYear(AValue)+1);
  661. end;
  662. Function HourOfTheYear(const AValue: TDateTime): Word;
  663. Var
  664. H,M,S,MS : Word;
  665. begin
  666. DecodeTime(AValue,H,M,S,MS);
  667. Result:=H+((DayOfTheYear(AValue)-1)*24);
  668. end;
  669. Function MinuteOfTheYear(const AValue: TDateTime): LongWord;
  670. Var
  671. H,M,S,MS : Word;
  672. begin
  673. DecodeTime(AValue,H,M,S,MS);
  674. Result:=M+(H+((DayOfTheYear(AValue)-1)*24))*60;
  675. end;
  676. Function SecondOfTheYear(const AValue: TDateTime): LongWord;
  677. Var
  678. H,M,S,MS : Word;
  679. begin
  680. DecodeTime(AValue,H,M,S,MS);
  681. Result:=(M+(H+((DayOfTheYear(AValue)-1)*24))*60)*60+S;
  682. end;
  683. Function MilliSecondOfTheYear(const AValue: TDateTime): Int64;
  684. Var
  685. H,M,S,MS : Word;
  686. begin
  687. DecodeTime(AValue,H,M,S,MS);
  688. Result:=((M+(H+((int64(DayOfTheYear(AValue))-1)*24))*60)*60+S)*1000+MS;
  689. end;
  690. { ---------------------------------------------------------------------
  691. Part of month functions.
  692. ---------------------------------------------------------------------}
  693. Function WeekOfTheMonth(const AValue: TDateTime): Word;
  694. var
  695. Y,M,DOW : word;
  696. begin
  697. DecodeDateMonthWeek(AValue,Y,M,Result,DOW);
  698. end;
  699. Function WeekOfTheMonth(const AValue: TDateTime; var AYear, AMonth: Word): Word;
  700. Var
  701. DOW : Word;
  702. begin
  703. DecodeDateMonthWeek(AValue,AYear,AMonth,Result,DOW);
  704. end;
  705. Function DayOfTheMonth(const AValue: TDateTime): Word;
  706. Var
  707. Y,M : Word;
  708. begin
  709. DecodeDate(AValue,Y,M,Result);
  710. end;
  711. Function HourOfTheMonth(const AValue: TDateTime): Word;
  712. Var
  713. Y,M,D,H,N,S,MS : Word;
  714. begin
  715. DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
  716. Result:=(D-1)*24+H;
  717. end;
  718. Function MinuteOfTheMonth(const AValue: TDateTime): Word;
  719. Var
  720. Y,M,D,H,N,S,MS : Word;
  721. begin
  722. DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
  723. Result:=((D-1)*24+H)*60+N;
  724. end;
  725. Function SecondOfTheMonth(const AValue: TDateTime): LongWord;
  726. Var
  727. Y,M,D,H,N,S,MS : Word;
  728. begin
  729. DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
  730. Result:=(((D-1)*24+H)*60+N)*60+S;
  731. end;
  732. Function MilliSecondOfTheMonth(const AValue: TDateTime): LongWord;
  733. Var
  734. Y,M,D,H,N,S,MS : Word;
  735. begin
  736. DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
  737. Result:=((((D-1)*24+H)*60+N)*60+S)*1000+MS;
  738. end;
  739. { ---------------------------------------------------------------------
  740. Part of week functions.
  741. ---------------------------------------------------------------------}
  742. Function DayOfTheWeek(const AValue: TDateTime): Word;
  743. begin
  744. Result:=DowMAP[DayOfWeek(AValue)];
  745. end;
  746. Function HourOfTheWeek(const AValue: TDateTime): Word;
  747. Var
  748. H,M,S,MS : Word;
  749. begin
  750. DecodeTime(AValue,H,M,S,MS);
  751. Result:=(DayOfTheWeek(AValue)-1)*24+H;
  752. end;
  753. Function MinuteOfTheWeek(const AValue: TDateTime): Word;
  754. Var
  755. H,M,S,MS : Word;
  756. begin
  757. DecodeTime(AValue,H,M,S,MS);
  758. Result:=((DayOfTheWeek(AValue)-1)*24+H)*60+M;
  759. end;
  760. Function SecondOfTheWeek(const AValue: TDateTime): LongWord;
  761. Var
  762. H,M,S,MS : Word;
  763. begin
  764. DecodeTime(AValue,H,M,S,MS);
  765. Result:=(((DayOfTheWeek(AValue)-1)*24+H)*60+M)*60+S;
  766. end;
  767. Function MilliSecondOfTheWeek(const AValue: TDateTime): LongWord;
  768. Var
  769. H,M,S,MS : Word;
  770. begin
  771. DecodeTime(AValue,H,M,S,MS);
  772. Result:=((((DayOfTheWeek(AValue)-1)*24+H)*60+M)*60+S)*1000+MS;
  773. end;
  774. { ---------------------------------------------------------------------
  775. Part of day functions.
  776. ---------------------------------------------------------------------}
  777. Function HourOfTheDay(const AValue: TDateTime): Word;
  778. Var
  779. M,S,MS : Word;
  780. begin
  781. DecodeTime(AValue,Result,M,S,MS);
  782. end;
  783. Function MinuteOfTheDay(const AValue: TDateTime): Word;
  784. Var
  785. H,M,S,MS : Word;
  786. begin
  787. DecodeTime(AValue,H,M,S,MS);
  788. Result:=(H*60)+M;
  789. end;
  790. Function SecondOfTheDay(const AValue: TDateTime): LongWord;
  791. Var
  792. H,M,S,MS : Word;
  793. begin
  794. DecodeTime(AValue,H,M,S,MS);
  795. Result:=((H*60)+M)*60+S;
  796. end;
  797. Function MilliSecondOfTheDay(const AValue: TDateTime): LongWord;
  798. Var
  799. H,M,S,MS : Word;
  800. begin
  801. DecodeTime(AValue,H,M,S,MS);
  802. Result:=(((H*60)+M)*60+S)*1000+MS;
  803. end;
  804. { ---------------------------------------------------------------------
  805. Part of hour functions.
  806. ---------------------------------------------------------------------}
  807. Function MinuteOfTheHour(const AValue: TDateTime): Word;
  808. Var
  809. H,S,MS : Word;
  810. begin
  811. DecodeTime(AValue,H,Result,S,MS);
  812. end;
  813. Function SecondOfTheHour(const AValue: TDateTime): Word;
  814. Var
  815. H,S,M,MS : Word;
  816. begin
  817. DecodeTime(AValue,H,M,S,MS);
  818. Result:=M*60+S;
  819. end;
  820. Function MilliSecondOfTheHour(const AValue: TDateTime): LongWord;
  821. Var
  822. H,S,M,MS : Word;
  823. begin
  824. DecodeTime(AValue,H,M,S,MS);
  825. Result:=(M*60+S)*1000+MS;
  826. end;
  827. { ---------------------------------------------------------------------
  828. Part of minute functions.
  829. ---------------------------------------------------------------------}
  830. Function SecondOfTheMinute(const AValue: TDateTime): Word;
  831. Var
  832. H,M,MS : Word;
  833. begin
  834. DecodeTime(AValue,H,M,Result,MS);
  835. end;
  836. Function MilliSecondOfTheMinute(const AValue: TDateTime): LongWord;
  837. Var
  838. H,S,M,MS : Word;
  839. begin
  840. DecodeTime(AValue,H,M,S,MS);
  841. Result:=S*1000+MS;
  842. end;
  843. { ---------------------------------------------------------------------
  844. Part of second functions.
  845. ---------------------------------------------------------------------}
  846. Function MilliSecondOfTheSecond(const AValue: TDateTime): Word;
  847. Var
  848. H,M,S : Word;
  849. begin
  850. DecodeTime(AValue,H,M,S,Result);
  851. end;
  852. { ---------------------------------------------------------------------
  853. Range checking functions.
  854. ---------------------------------------------------------------------}
  855. Function WithinPastYears(const ANow, AThen: TDateTime; const AYears: Integer): Boolean;
  856. begin
  857. Result:=YearsBetween(ANow,AThen)<=AYears;
  858. end;
  859. Function WithinPastMonths(const ANow, AThen: TDateTime; const AMonths: Integer): Boolean;
  860. begin
  861. Result:=MonthsBetween(ANow,AThen)<=AMonths;
  862. end;
  863. Function WithinPastWeeks(const ANow, AThen: TDateTime; const AWeeks: Integer): Boolean;
  864. begin
  865. Result:=WeeksBetween(ANow,AThen)<=AWeeks;
  866. end;
  867. Function WithinPastDays(const ANow, AThen: TDateTime; const ADays: Integer): Boolean;
  868. begin
  869. Result:=DaysBetween(ANow,AThen)<=ADays;
  870. end;
  871. Function WithinPastHours(const ANow, AThen: TDateTime; const AHours: Int64): Boolean;
  872. begin
  873. Result:=HoursBetween(ANow,AThen)<=AHours;
  874. end;
  875. Function WithinPastMinutes(const ANow, AThen: TDateTime; const AMinutes: Int64): Boolean;
  876. begin
  877. Result:=MinutesBetween(ANow,AThen)<=AMinutes;
  878. end;
  879. Function WithinPastSeconds(const ANow, AThen: TDateTime; const ASeconds: Int64): Boolean;
  880. begin
  881. Result:=SecondsBetween(ANow,Athen)<=ASeconds;
  882. end;
  883. Function WithinPastMilliSeconds(const ANow, AThen: TDateTime; const AMilliSeconds: Int64): Boolean;
  884. begin
  885. Result:=MilliSecondsBetween(ANow,AThen)<=AMilliSeconds;
  886. end;
  887. { ---------------------------------------------------------------------
  888. Period functions.
  889. ---------------------------------------------------------------------}
  890. {
  891. These functions are declared as approximate by Borland.
  892. A bit strange, since it can be calculated exactly ?
  893. }
  894. Function YearsBetween(const ANow, AThen: TDateTime): Integer;
  895. begin
  896. Result:=Trunc(Abs(ANow-AThen)/ApproxDaysPerYear);
  897. end;
  898. Function MonthsBetween(const ANow, AThen: TDateTime): Integer;
  899. begin
  900. Result:=Trunc(Abs(ANow-Athen)/ApproxDaysPerMonth);
  901. end;
  902. Function WeeksBetween(const ANow, AThen: TDateTime): Integer;
  903. begin
  904. Result:=Trunc(Abs(ANow-AThen)) div 7;
  905. end;
  906. Function DaysBetween(const ANow, AThen: TDateTime): Integer;
  907. begin
  908. Result:=Trunc(Abs(ANow-AThen));
  909. end;
  910. Function HoursBetween(const ANow, AThen: TDateTime): Int64;
  911. begin
  912. Result:=Trunc(Abs(ANow-AThen)*HoursPerDay);
  913. end;
  914. Function MinutesBetween(const ANow, AThen: TDateTime): Int64;
  915. begin
  916. Result:=Trunc(Abs(ANow-AThen)*MinsPerDay);
  917. end;
  918. Function SecondsBetween(const ANow, AThen: TDateTime): Int64;
  919. begin
  920. Result:=Trunc(Abs(ANow-AThen)*SecsPerDay);
  921. end;
  922. Function MilliSecondsBetween(const ANow, AThen: TDateTime): Int64;
  923. begin
  924. Result:=Trunc(Abs(ANow-AThen)*MSecsPerDay);
  925. end;
  926. { ---------------------------------------------------------------------
  927. Timespan in xxx functions.
  928. ---------------------------------------------------------------------}
  929. Function YearSpan(const ANow, AThen: TDateTime): Double;
  930. begin
  931. Result:=Abs(Anow-Athen)/ApproxDaysPerYear;
  932. end;
  933. Function MonthSpan(const ANow, AThen: TDateTime): Double;
  934. begin
  935. Result:=Abs(ANow-AThen)/ApproxDaysPerMonth;
  936. end;
  937. Function WeekSpan(const ANow, AThen: TDateTime): Double;
  938. begin
  939. Result:=Abs(ANow-AThen) / 7
  940. end;
  941. Function DaySpan(const ANow, AThen: TDateTime): Double;
  942. begin
  943. Result:=Abs(ANow-AThen);
  944. end;
  945. Function HourSpan(const ANow, AThen: TDateTime): Double;
  946. begin
  947. Result:=Abs(ANow-AThen)*HoursPerDay;
  948. end;
  949. Function MinuteSpan(const ANow, AThen: TDateTime): Double;
  950. begin
  951. Result:=Abs(ANow-AThen)*MinsPerDay;
  952. end;
  953. Function SecondSpan(const ANow, AThen: TDateTime): Double;
  954. begin
  955. Result:=Abs(ANow-AThen)*SecsPerDay;
  956. end;
  957. Function MilliSecondSpan(const ANow, AThen: TDateTime): Double;
  958. begin
  959. Result:=Abs(ANow-AThen)*MSecsPerDay;
  960. end;
  961. { ---------------------------------------------------------------------
  962. Increment/decrement functions.
  963. ---------------------------------------------------------------------}
  964. Function IncYear(const AValue: TDateTime; const ANumberOfYears: Integer ): TDateTime;
  965. Var
  966. Y,M,D,H,N,S,MS : Word;
  967. begin
  968. DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
  969. Y:=Y+ANumberOfYears;
  970. If (M=2) and (D=29) And (Not IsLeapYear(Y)) then
  971. D:=28;
  972. Result:=EncodeDateTime(Y,M,D,H,N,S,MS);
  973. end;
  974. Function IncYear(const AValue: TDateTime): TDateTime; // ; const ANumberOfYears: Integer = 1)
  975. begin
  976. Result:=IncYear(Avalue,1);
  977. end;
  978. Function IncWeek(const AValue: TDateTime; const ANumberOfWeeks: Integer): TDateTime;
  979. begin
  980. Result:=AValue+ANumberOfWeeks*7;
  981. end;
  982. Function IncWeek(const AValue: TDateTime): TDateTime; // ; const ANumberOfWeeks: Integer = 1)
  983. begin
  984. Result:=IncWeek(Avalue,1);
  985. end;
  986. Function IncDay(const AValue: TDateTime; const ANumberOfDays: Integer): TDateTime;
  987. begin
  988. Result:=AValue+ANumberOfDays;
  989. end;
  990. Function IncDay(const AValue: TDateTime): TDateTime; //; const ANumberOfDays: Integer = 1)
  991. begin
  992. Result:=IncDay(Avalue,1);
  993. end;
  994. Function IncHour(const AValue: TDateTime; const ANumberOfHours: Int64): TDateTime;
  995. begin
  996. Result:=AValue+ANumberOfHours/HoursPerDay;
  997. end;
  998. Function IncHour(const AValue: TDateTime): TDateTime; //; const ANumberOfHours: Int64 = 1
  999. begin
  1000. Result:=IncHour(AValue,1);
  1001. end;
  1002. Function IncMinute(const AValue: TDateTime; const ANumberOfMinutes: Int64): TDateTime;
  1003. begin
  1004. Result:=AValue+ANumberOfMinutes / MinsPerDay;
  1005. end;
  1006. Function IncMinute(const AValue: TDateTime): TDateTime; // ; const ANumberOfMinutes: Int64 = 1
  1007. begin
  1008. Result:=IncMinute(AValue,1);
  1009. end;
  1010. Function IncSecond(const AValue: TDateTime; const ANumberOfSeconds: Int64): TDateTime;
  1011. begin
  1012. Result:=AValue+ANumberOfSeconds / SecsPerDay;
  1013. end;
  1014. Function IncSecond(const AValue: TDateTime): TDateTime; // ; const ANumberOfSeconds: Int64 = 1
  1015. begin
  1016. Result:=IncSecond(Avalue,1);
  1017. end;
  1018. Function IncMilliSecond(const AValue: TDateTime; const ANumberOfMilliSeconds: Int64): TDateTime;
  1019. begin
  1020. Result:=AValue+ANumberOfMilliSeconds/MSecsPerDay;
  1021. end;
  1022. Function IncMilliSecond(const AValue: TDateTime): TDateTime; // ; const ANumberOfMilliSeconds: Int64 = 1
  1023. begin
  1024. Result:=IncMilliSecond(AValue,1);
  1025. end;
  1026. { ---------------------------------------------------------------------
  1027. Encode/Decode of complete timestamp
  1028. ---------------------------------------------------------------------}
  1029. Function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word): TDateTime;
  1030. begin
  1031. If Not TryEncodeDateTime(AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond,Result) then
  1032. InvalidDateTimeError(AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond)
  1033. end;
  1034. Procedure DecodeDateTime(const AValue: TDateTime; var AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word);
  1035. begin
  1036. DecodeDate(AValue,AYear,AMonth,ADay);
  1037. DecodeTime(AValue,AHour,AMinute,ASecond,AMilliSecond);
  1038. end;
  1039. Function TryEncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word; var AValue: TDateTime): Boolean;
  1040. Var
  1041. tmp : TDateTime;
  1042. begin
  1043. Result:=TryEncodeDate(AYear,AMonth,ADay,AValue);
  1044. Result:=Result and TryEncodeTime(AHour,AMinute,ASecond,Amillisecond,Tmp);
  1045. If Result then
  1046. Avalue:=ComposeDateTime(AValue,Tmp);
  1047. end;
  1048. { ---------------------------------------------------------------------
  1049. Encode/decode date, specifying week of year and day of week
  1050. ---------------------------------------------------------------------}
  1051. Function EncodeDateWeek(const AYear, AWeekOfYear: Word; const ADayOfWeek: Word): TDateTime;
  1052. begin
  1053. If Not TryEncodeDateWeek(AYear,AWeekOfYear,Result,ADayOfWeek) then
  1054. InvalidDateWeekError(AYear,AWeekOfYear,ADayOfWeek);
  1055. end;
  1056. Function EncodeDateWeek(const AYear, AWeekOfYear: Word): TDateTime; //; const ADayOfWeek: Word = 1
  1057. begin
  1058. Result := EncodeDateWeek(AYear,AWeekOfYear,1);
  1059. end;
  1060. Procedure DecodeDateWeek(const AValue: TDateTime; var AYear, AWeekOfYear, ADayOfWeek: Word);
  1061. var
  1062. DOY : Integer;
  1063. D: Word;
  1064. YS : TDateTime;
  1065. YSDOW, YEDOW: Word;
  1066. begin
  1067. AYear:=YearOf(AValue);
  1068. // Correct to ISO DOW
  1069. ADayOfWeek:=DayOfWeek(AValue)-1;
  1070. If ADAyOfWeek=0 then
  1071. ADayofweek:=7;
  1072. YS:=StartOfAYear(AYear);
  1073. DOY:=Trunc(AValue-YS)+1;
  1074. YSDOW:=DayOfTheWeek(YS);
  1075. // Correct week if later than wednesday. First week never starts later than wednesday
  1076. if (YSDOW<5) then
  1077. Inc(DOY,YSDOW-1)
  1078. else
  1079. Dec(DOY,8-YSDOW);
  1080. if (DOY<=0) then // Day is in last week of previous year.
  1081. DecodeDateWeek(YS-1,AYear,AWeekOfYear,D)
  1082. else
  1083. begin
  1084. AWeekOfYear:=DOY div 7;
  1085. if ((DOY mod 7)<>0) then
  1086. Inc(AWeekOfYear);
  1087. if (AWeekOfYear>52) then // Maybe in first week of next year ?
  1088. begin
  1089. YEDOW:=YSDOW;
  1090. if IsLeapYear(AYear) then
  1091. begin
  1092. Inc(YEDOW);
  1093. if (YEDOW>7) then
  1094. YEDOW:=1
  1095. else
  1096. end;
  1097. if (YEDOW<4) then // Really next year.
  1098. begin
  1099. Inc(AYear);
  1100. AWeekOfYear:=1;
  1101. end;
  1102. end;
  1103. end;
  1104. end;
  1105. Function TryEncodeDateWeek(const AYear, AWeekOfYear: Word; var AValue: TDateTime; const ADayOfWeek: Word): Boolean;
  1106. Var
  1107. DOW : Word;
  1108. Rest : Integer;
  1109. begin
  1110. Result:=IsValidDateWeek(Ayear,AWeekOfYear,ADayOfWeek);
  1111. If Result then
  1112. begin
  1113. AValue:=EncodeDate(AYear,1,1)+(7*(AWeekOfYear-1));
  1114. DOW:=DayOfTheWeek(AValue);
  1115. Rest:=ADayOfWeek-DOW;
  1116. If (DOW>4) then
  1117. Inc(Rest,7);
  1118. AValue:=AValue+Rest;
  1119. end;
  1120. end;
  1121. Function TryEncodeDateWeek(const AYear, AWeekOfYear: Word; var AValue: TDateTime): Boolean; //; const ADayOfWeek: Word = 1
  1122. begin
  1123. Result:=TryEncodeDateWeek(AYear,AWeekOfYear,AValue,1);
  1124. end;
  1125. { ---------------------------------------------------------------------
  1126. Encode/decode date, specifying day of year
  1127. ---------------------------------------------------------------------}
  1128. Function EncodeDateDay(const AYear, ADayOfYear: Word): TDateTime;
  1129. begin
  1130. If Not TryEncodeDateDay(AYear,ADayOfYear,Result) then
  1131. InvalidDateDayError(AYear,ADayOfYear);
  1132. end;
  1133. Procedure DecodeDateDay(const AValue: TDateTime; var AYear, ADayOfYear: Word);
  1134. Var
  1135. M,D : Word;
  1136. begin
  1137. DecodeDate(AValue,AYear,M,D);
  1138. ADayOfyear:=Trunc(AValue-EncodeDate(AYear,1,1))+1;
  1139. end;
  1140. Function TryEncodeDateDay(const AYear, ADayOfYear: Word; var AValue: TDateTime): Boolean;
  1141. begin
  1142. Result:=(ADayOfYear<>0) and (ADayOfYear<=DaysPerYear [IsleapYear(AYear)]);
  1143. If Result then
  1144. AValue:=EncodeDate(AYear,1,1)+ADayOfYear-1;
  1145. end;
  1146. { ---------------------------------------------------------------------
  1147. Encode/decode date, specifying week of month
  1148. ---------------------------------------------------------------------}
  1149. Function EncodeDateMonthWeek(const AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word): TDateTime;
  1150. begin
  1151. If Not TryEncodeDateMonthWeek(Ayear,AMonth,AWeekOfMonth,ADayOfWeek,Result) then
  1152. InvalidDateMonthWeekError(AYear,AMonth,AWeekOfMonth,ADayOfWeek);
  1153. end;
  1154. Procedure DecodeDateMonthWeek(const AValue: TDateTime; var AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word);
  1155. Var
  1156. D,SDOM,EDOM : Word;
  1157. SOM : TdateTime;
  1158. DOM : Integer;
  1159. begin
  1160. DecodeDate(AValue,AYear,AMonth,D);
  1161. ADayOfWeek:=DayOfTheWeek(AValue);
  1162. SOM:=EncodeDate(Ayear,Amonth,1);
  1163. SDOM:=DayOfTheWeek(SOM);
  1164. DOM:=D-1+SDOM;
  1165. If SDOM>4 then
  1166. Dec(DOM,7);
  1167. // Too early in the month. First full week is next week, day is after thursday.
  1168. If DOM<=0 Then
  1169. DecodeDateMonthWeek(SOM-1,AYear,AMonth,AWeekOfMonth,D)
  1170. else
  1171. begin
  1172. AWeekOfMonth:=(DOM div 7)+Ord((DOM mod 7)<>0);
  1173. EDOM:=DayOfTheWeek(EndOfAMonth(Ayear,AMonth));
  1174. // In last days of last long week, so in next month...
  1175. If (EDOM<4) and ((DaysInAMonth(AYear,Amonth)-D)<EDOM) then
  1176. begin
  1177. AWeekOfMonth:=1;
  1178. Inc(AMonth);
  1179. If (AMonth=13) then
  1180. begin
  1181. AMonth:=1;
  1182. Inc(AYear);
  1183. end;
  1184. end;
  1185. end;
  1186. end;
  1187. Function TryEncodeDateMonthWeek(const AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word; var AValue: TDateTime): Boolean;
  1188. var
  1189. S : Word;
  1190. DOM : Integer;
  1191. begin
  1192. Result:=IsValidDateMonthWeek(AYear,AMonth,AWeekOfMonth,ADayOfWeek);
  1193. if Result then
  1194. begin
  1195. AValue:=EncodeDate(AYear,AMonth,1);
  1196. DOM:=(AWeekOfMonth-1)*7+ADayOfWeek-1;
  1197. { Correct for first week in last month.}
  1198. S:=DayOfTheWeek(AValue);
  1199. Dec(DOM,S-1);
  1200. if S in [DayFriday..DaySunday] then
  1201. Inc(DOM,7);
  1202. AValue:=AValue+DOM;
  1203. end;
  1204. end;
  1205. { ---------------------------------------------------------------------
  1206. Replace given element with supplied value.
  1207. ---------------------------------------------------------------------}
  1208. Const
  1209. LFAI = RecodeLeaveFieldAsIS; // Less typing, readable code
  1210. {
  1211. Note: We have little choice but to implement it like Borland did:
  1212. If AValue contains some 'wrong' value, it will throw an error.
  1213. To simulate this we'd have to check in each function whether
  1214. both arguments are correct. To avoid it, all is routed through
  1215. the 'central' RecodeDateTime function as in Borland's implementation.
  1216. }
  1217. Function RecodeYear(const AValue: TDateTime; const AYear: Word): TDateTime;
  1218. begin
  1219. Result := RecodeDateTime(AValue,AYear,LFAI,LFAI,LFAI,LFAI,LFAI,LFAI);
  1220. end;
  1221. Function RecodeMonth(const AValue: TDateTime; const AMonth: Word): TDateTime;
  1222. begin
  1223. Result := RecodeDateTime(AValue,LFAI,AMonth,LFAI,LFAI,LFAI,LFAI,LFAI);
  1224. end;
  1225. Function RecodeDay(const AValue: TDateTime; const ADay: Word): TDateTime;
  1226. begin
  1227. Result := RecodeDateTime(AValue,LFAI,LFAI,ADay,LFAI,LFAI,LFAI,LFAI);
  1228. end;
  1229. Function RecodeHour(const AValue: TDateTime; const AHour: Word): TDateTime;
  1230. begin
  1231. Result := RecodeDateTime(AValue,LFAI,LFAI,LFAI,AHour,LFAI,LFAI,LFAI);
  1232. end;
  1233. Function RecodeMinute(const AValue: TDateTime; const AMinute: Word): TDateTime;
  1234. begin
  1235. Result := RecodeDateTime(AValue,LFAI,LFAI,LFAI,LFAI,AMinute,LFAI,LFAI);
  1236. end;
  1237. Function RecodeSecond(const AValue: TDateTime; const ASecond: Word): TDateTime;
  1238. begin
  1239. Result := RecodeDateTime(AValue,LFAI,LFAI,LFAI,LFAI,LFAI,ASecond,LFAI);
  1240. end;
  1241. Function RecodeMilliSecond(const AValue: TDateTime; const AMilliSecond: Word): TDateTime;
  1242. begin
  1243. Result := RecodeDateTime(AValue,LFAI,LFAI,LFAI,LFAI,LFAI,LFAI,AMilliSecond);
  1244. end;
  1245. Function RecodeDate(const AValue: TDateTime; const AYear, AMonth, ADay: Word): TDateTime;
  1246. begin
  1247. Result := RecodeDateTime(AValue,AYear,AMonth,ADay,LFAI,LFAI,LFAI,LFAI);
  1248. end;
  1249. Function RecodeTime(const AValue: TDateTime; const AHour, AMinute, ASecond, AMilliSecond: Word): TDateTime;
  1250. begin
  1251. Result := RecodeDateTime(AValue,LFAI,LFAI,LFAI,AHour,AMinute,ASecond,AMilliSecond);
  1252. end;
  1253. Function RecodeDateTime(const AValue: TDateTime; const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word): TDateTime;
  1254. begin
  1255. If Not TryRecodeDateTime(AValue,AYear,AMonth,ADay,AHour,AMinute,ASecond,AMilliSecond,Result) then
  1256. InvalidDateTimeError(AYear,AMonth,ADay,AHour,AMinute,ASecond,AMilliSecond,AValue);
  1257. end;
  1258. Function TryRecodeDateTime(const AValue: TDateTime; const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word; var AResult: TDateTime): Boolean;
  1259. Procedure FV (Var AV : Word; Arg : Word);
  1260. begin
  1261. If (Arg<>LFAI) then
  1262. AV:=Arg;
  1263. end;
  1264. Var
  1265. Y,M,D,H,N,S,MS : Word;
  1266. begin
  1267. DecodeDateTime(AValue,Y,M,D,H,N,S,MS);
  1268. FV(Y,AYear);
  1269. FV(M,AMonth);
  1270. FV(D,ADay);
  1271. FV(H,AHour);
  1272. FV(N,AMinute);
  1273. FV(S,ASecond);
  1274. FV(MS,AMillisecond);
  1275. Result:=TryEncodeDateTime(Y,M,D,H,N,S,MS,AResult);
  1276. end;
  1277. { ---------------------------------------------------------------------
  1278. Comparision of date/time
  1279. ---------------------------------------------------------------------}
  1280. Function CompareDateTime(const A, B: TDateTime): TValueRelationship;
  1281. begin
  1282. If SameDateTime(A,B) then
  1283. Result:=EqualsValue
  1284. else If A>B then
  1285. Result:=GreaterThanValue
  1286. else
  1287. Result:=LessThanValue
  1288. end;
  1289. Function CompareDate(const A, B: TDateTime): TValueRelationship;
  1290. begin
  1291. If SameDate(A,B) then
  1292. Result:=EQualsValue
  1293. else if A<B then
  1294. Result:=LessThanValue
  1295. else
  1296. Result:=GreaterThanValue;
  1297. end;
  1298. Function CompareTime(const A, B: TDateTime): TValueRelationship;
  1299. begin
  1300. If SameTime(A,B) then
  1301. Result:=EQualsValue
  1302. else If Frac(A)<Frac(B) then
  1303. Result:=LessThanValue
  1304. else
  1305. Result:=GreaterThanValue;
  1306. end;
  1307. Function SameDateTime(const A, B: TDateTime): Boolean;
  1308. begin
  1309. Result:=Abs(A-B)<OneMilliSecond;
  1310. end;
  1311. Function SameDate(const A, B: TDateTime): Boolean;
  1312. begin
  1313. Result:=Trunc(A)=Trunc(B);
  1314. end;
  1315. Function SameTime(const A, B: TDateTime): Boolean;
  1316. begin
  1317. Result:=Frac(Abs(A-B))<OneMilliSecond;
  1318. end;
  1319. Function InternalNthDayOfWeek(DoM : Word) : Word;
  1320. begin
  1321. Result:=(Dom-1) div 7 +1;
  1322. end;
  1323. Function NthDayOfWeek(const AValue: TDateTime): Word;
  1324. begin
  1325. Result:=InternalNthDayOfWeek(DayOfTheMonth(AValue));
  1326. end;
  1327. Procedure DecodeDayOfWeekInMonth(const AValue: TDateTime; var AYear, AMonth, ANthDayOfWeek, ADayOfWeek: Word);
  1328. var
  1329. D: Word;
  1330. begin
  1331. DecodeDate(AValue,AYear,AMonth,D);
  1332. ADayOfWeek:=DayOfTheWeek(AValue);
  1333. ANthDayOfWeek:=InternalNthDayOfWeek(D);
  1334. end;
  1335. Function EncodeDayOfWeekInMonth(const AYear, AMonth, ANthDayOfWeek, ADayOfWeek: Word): TDateTime;
  1336. begin
  1337. If Not TryEncodeDayOfWeekInMonth(AYear,AMonth,ANthDayOfWeek,ADayOfWeek,Result) then
  1338. InvalidDayOfWeekInMonthError(AYear,AMonth,ANthDayOfWeek,ADayOfWeek);
  1339. end;
  1340. Function TryEncodeDayOfWeekInMonth(const AYear, AMonth, ANthDayOfWeek, ADayOfWeek: Word; var AValue: TDateTime): Boolean;
  1341. Var
  1342. SOM,D : Word;
  1343. begin
  1344. SOM:=DayOfTheWeek(EncodeDate(Ayear,AMonth,1));
  1345. D:=1+ADayOfWeek-SOM+7*(ANthDayOfWeek-1);
  1346. If SOM>ADayOfWeek then
  1347. D:=D+7; // Clearer would have been Inc(ANthDayOfweek) but it's a const
  1348. Result:=TryEncodeDate(Ayear,AMonth,D,AValue);
  1349. end;
  1350. { ---------------------------------------------------------------------
  1351. Exception throwing routines
  1352. ---------------------------------------------------------------------}
  1353. Procedure InvalidDateTimeError(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word; const ABaseDate: TDateTime);
  1354. Function DoField(Arg,Def : Word; Unknown: String) : String;
  1355. begin
  1356. If (Arg<>LFAI) then
  1357. Result:=Format('%.*d',[Length(Unknown),Arg])
  1358. else if (ABaseDate=0) then
  1359. Result:=Unknown
  1360. else
  1361. Result:=Format('%.*d',[Length(Unknown),Arg]);
  1362. end;
  1363. Var
  1364. Y,M,D,H,N,S,MS : Word;
  1365. Msg : String;
  1366. begin
  1367. DecodeDateTime(ABasedate,Y,M,D,H,N,S,MS);
  1368. Msg:=DoField(AYear,Y,'????');
  1369. Msg:=Msg+DateSeparator+DoField(AMonth,M,'??');
  1370. Msg:=Msg+DateSeparator+DoField(ADay,D,'??');
  1371. Msg:=Msg+' '+DoField(AHour,H,'??');
  1372. Msg:=Msg+TimeSeparator+DoField(AMinute,N,'??');
  1373. Msg:=Msg+TimeSeparator+Dofield(ASecond,S,'??');
  1374. Msg:=Msg+DecimalSeparator+DoField(AMilliSecond,MS,'???');
  1375. Raise EConvertError.CreateFmt(SErrInvalidTimeStamp,[Msg]);
  1376. end;
  1377. Procedure InvalidDateTimeError(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Word); // const ABaseDate: TDateTime = 0
  1378. begin
  1379. InvalidDateTimeError(AYear,AMonth,ADay,AHour,AMinute,ASecond,AMilliSecond,0);
  1380. end;
  1381. Procedure InvalidDateWeekError(const AYear, AWeekOfYear, ADayOfWeek: Word);
  1382. begin
  1383. Raise EConvertError.CreateFmt(SErrInvalidDateWeek,[AYear,AWeekOfYear,ADayOfWeek]);
  1384. end;
  1385. Procedure InvalidDateDayError(const AYear, ADayOfYear: Word);
  1386. begin
  1387. Raise EConvertError.CreateFmt(SErrInvalidDayOfYear,[AYear,ADayOfYear]);
  1388. end;
  1389. Procedure InvalidDateMonthWeekError(const AYear, AMonth, AWeekOfMonth, ADayOfWeek: Word);
  1390. begin
  1391. Raise EConvertError.CreateFmt(SErrInvalidDateMonthWeek,[Ayear,AMonth,AWeekOfMonth,ADayOfWeek]);
  1392. end;
  1393. Procedure InvalidDayOfWeekInMonthError(const AYear, AMonth, ANthDayOfWeek, ADayOfWeek: Word);
  1394. begin
  1395. Raise EConvertError.CreateFmt(SErrInvalidDayOfWeekInMonth,[AYear,AMonth,ANthDayOfWeek,ADayOfWeek]);
  1396. end;
  1397. { ---------------------------------------------------------------------
  1398. Julian and Modified Julian Date conversion support
  1399. ---------------------------------------------------------------------}
  1400. {$ifopt R+}
  1401. {$define RangeCheckWasOn}
  1402. {$R-}
  1403. {$endif opt R+}
  1404. {$ifopt Q+}
  1405. {$define OverflowCheckWasOn}
  1406. {$Q-}
  1407. {$endif opt Q+}
  1408. Function DateTimeToJulianDate(const AValue: TDateTime): Double;
  1409. begin
  1410. DateTimeToJulianDate := AValue - JulianEpoch;
  1411. end;
  1412. Function JulianDateToDateTime(const AValue: Double): TDateTime;
  1413. begin
  1414. JulianDateToDateTime := AValue + JulianEpoch;
  1415. if(AValue <= 0) or (AValue >= 10000)then
  1416. JulianDateToDateTime := NaN;
  1417. end;
  1418. Function TryJulianDateToDateTime(const AValue: Double; var ADateTime: TDateTime): Boolean;
  1419. begin
  1420. ADateTime := JulianDateToDateTime(AValue);
  1421. TryJulianDateToDateTime := ADateTime <> NaN;
  1422. end;
  1423. Function DateTimeToModifiedJulianDate(const AValue: TDateTime): Double;
  1424. begin
  1425. Result:=0;
  1426. NotYetImplemented('DateTimeToModifiedJulianDate');
  1427. end;
  1428. Function ModifiedJulianDateToDateTime(const AValue: Double): TDateTime;
  1429. begin
  1430. Result:=0;
  1431. NotYetImplemented('ModifiedJulianDateToDateTime');
  1432. end;
  1433. Function TryModifiedJulianDateToDateTime(const AValue: Double; var ADateTime: TDateTime): Boolean;
  1434. begin
  1435. Result:=False;
  1436. NotYetImplemented('TryModifiedJulianDateToDateTime');
  1437. end;
  1438. {$ifdef RangeCheckWasOn}
  1439. {$R+}
  1440. {$undef RangeCheckWasOn}
  1441. {$endif}
  1442. {$ifdef OverflowCheckWasOn}
  1443. {$Q+}
  1444. {$undef OverflowCheckWasOn}
  1445. {$endif}
  1446. { ---------------------------------------------------------------------
  1447. Unix timestamp support.
  1448. ---------------------------------------------------------------------}
  1449. Function DateTimeToUnix(const AValue: TDateTime): Int64;
  1450. begin
  1451. Result:=SecondsBetween(UnixEpoch, AValue);
  1452. end;
  1453. Function UnixToDateTime(const AValue: Int64): TDateTime;
  1454. begin
  1455. Result:=IncSecond(UnixEpoch, AValue);
  1456. end;
  1457. Function UnixTimeStampToMac(const AValue: Int64): Int64;
  1458. const
  1459. Epoch=24107 * 24 * 3600;
  1460. begin
  1461. Result:=AValue + Epoch;
  1462. end;
  1463. { ---------------------------------------------------------------------
  1464. Mac timestamp support.
  1465. ---------------------------------------------------------------------}
  1466. Function DateTimeToMac(const AValue: TDateTime): Int64;
  1467. var
  1468. Epoch:TDateTime;
  1469. begin
  1470. Epoch:=EncodeDateTime( 1904, 1, 1, 0, 0, 0, 0 );
  1471. Result:=SecondsBetween( Epoch, AValue );
  1472. end;
  1473. Function MacToDateTime(const AValue: Int64): TDateTime;
  1474. var
  1475. Epoch:TDateTime;
  1476. begin
  1477. Epoch:=EncodeDateTime( 1904, 1, 1, 0, 0, 0, 0 );
  1478. Result:=IncSecond( Epoch, AValue );
  1479. end;
  1480. Function MacTimeStampToUnix(const AValue: Int64): Int64;
  1481. const
  1482. Epoch=24107 * 24 * 3600;
  1483. begin
  1484. Result:=AValue - Epoch;
  1485. end;
  1486. Function DateTimeToDosDateTime(const AValue: TDateTime): longint;
  1487. var year,month,day,hour,min,sec,msec : word;
  1488. zs : longint;
  1489. begin
  1490. decodedatetime(avalue,year,month,day,hour,min,sec,msec);
  1491. result:=-1980;
  1492. result:=result+year and 127;
  1493. result:=result shl 4;
  1494. result:=result+month;
  1495. result:=result shl 5;
  1496. result:=result+day;
  1497. result:=result shl 16;
  1498. zs:=hour;
  1499. zs:=zs shl 6;
  1500. zs:=zs+min;
  1501. zs:=zs shl 5;
  1502. zs:=zs+sec div 2;
  1503. result:=result+(zs and $ffff);
  1504. end;
  1505. Function DosDateTimeToDateTime( AValue: longint): TDateTime;
  1506. var year,month,day,hour,min,sec : integer;
  1507. begin
  1508. sec:=(AValue and 31) * 2;
  1509. avalue:=AValue shr 5;
  1510. min:=AValue and 63;
  1511. avalue:=AValue shr 6;
  1512. hour:=AValue and 31;
  1513. avalue:=AValue shr 5;
  1514. day:=AValue and 31;
  1515. avalue:=AValue shr 5;
  1516. month:=AValue and 15;
  1517. avalue:=AValue shr 4;
  1518. year:=AValue+1980;
  1519. result:=EncodeDateTime(year,month,day,hour,min,sec,0);
  1520. end;
  1521. {
  1522. Inverse of formatdatetime, destined for the dateutils unit of FPC.
  1523. Limitations/implementation details:
  1524. - An inverse of FormatDateTime is not 100% an inverse, simply because one can put e.g. time tokens twice in the format string,
  1525. and scandatetime wouldn't know which time to pick.
  1526. - Strings like hn can't be reversed safely. E.g. 1:2 (2 minutes after 1) delivers 12 which is parsed as 12:00 and then
  1527. misses chars for the "n" part.
  1528. - trailing characters are ignored.
  1529. - no support for Eastern Asian formatting characters since they are windows only.
  1530. - no MBCS support.
  1531. Extensions
  1532. - #9 eats whitespace.
  1533. - whitespace at the end of a pattern is optional.
  1534. - ? matches any char.
  1535. - Quote the above chars to really match the char.
  1536. }
  1537. const whitespace = [' ',#13,#10];
  1538. hrfactor = 1/(24);
  1539. minfactor = 1/(24*60);
  1540. secfactor = 1/(24*60*60);
  1541. mssecfactor = 1/(24*60*60*1000);
  1542. const AMPMformatting : array[0..2] of string =('am/pm','a/p','ampm');
  1543. procedure raiseexception(const s:string);
  1544. begin
  1545. raise EConvertError.Create(s);
  1546. end;
  1547. function scandatetime(const pattern:string;const s:string;const fmt:TFormatSettings;startpos:integer=1) : tdatetime;
  1548. var len ,ind : integer;
  1549. yy,mm,dd : integer;
  1550. timeval : TDateTime;
  1551. activequote: char;
  1552. procedure intscandate(ptrn:pchar;plen:integer;poffs:integer);
  1553. // poffs is the offset to
  1554. var
  1555. pind : integer;
  1556. function findimatch(const mnts:array of string;p:pchar):integer;
  1557. var i : integer;
  1558. begin
  1559. result:=-1;
  1560. i:=0;
  1561. while (i<=high(mnts)) and (result=-1) do
  1562. begin
  1563. if AnsiStrLIComp(p,@mnts[i][1],length(mnts[i]))=0 then
  1564. result:=i;
  1565. inc(i);
  1566. end;
  1567. end;
  1568. procedure arraymatcherror;
  1569. begin
  1570. raiseexception(format(SNoArrayMatch,[pind+1,ind]))
  1571. end;
  1572. function findmatch(const mnts : array of string;const s:string):integer;
  1573. begin
  1574. result:=findimatch(mnts,@s[ind]);
  1575. if result=-1 then
  1576. arraymatcherror
  1577. else
  1578. begin
  1579. inc(ind,length(mnts[result])+1);
  1580. inc(pind,length(mnts[result])+1);
  1581. inc(result); // was 0 based.
  1582. end;
  1583. end;
  1584. var
  1585. pivot,
  1586. i : integer;
  1587. function scanfixedint(maxv:integer):integer;
  1588. var c : char;
  1589. oi:integer;
  1590. begin
  1591. result:=0;
  1592. oi:=ind;
  1593. c:=ptrn[pind];
  1594. while (pind<plen) and (ptrn[pind]=c) do inc(pind);
  1595. while (maxv>0) and (ind<=len) and (s[ind] IN ['0'..'9']) do
  1596. begin
  1597. result:=result*10+ord(s[ind])-48;
  1598. inc(ind);
  1599. dec(maxv);
  1600. end;
  1601. if oi=ind then
  1602. raiseexception(format(SPatternCharMismatch,[c,oi]));
  1603. end;
  1604. procedure matchchar(c:char);
  1605. begin
  1606. if (ind>len) or (s[ind]<>c) then
  1607. raiseexception(format(SNoCharMatch,[s[ind],c,pind+poffs+1,ind]));
  1608. inc(pind);
  1609. inc(ind);
  1610. end;
  1611. function scanpatlen:integer;
  1612. var c : char;
  1613. lind : Integer;
  1614. begin
  1615. result:=pind;
  1616. lind:=pind;
  1617. c:=ptrn[lind];
  1618. while (lind<=plen) and (ptrn[lind]=c) do
  1619. inc(lind);
  1620. result:=lind-result;
  1621. end;
  1622. procedure matchpattern(const lptr:string);
  1623. var len:integer;
  1624. begin
  1625. len:=length(lptr);
  1626. if len>0 then
  1627. intscandate(@lptr[1],len,pind+poffs);
  1628. end;
  1629. var lasttoken,lch : char;
  1630. begin
  1631. pind:=0; lasttoken:=' ';
  1632. while (ind<=len) and (pind<plen) do
  1633. begin
  1634. lch:=upcase(ptrn[pind]);
  1635. if activequote=#0 then
  1636. begin
  1637. if (lch='M') and (lasttoken='H') then
  1638. begin
  1639. i:=scanpatlen;
  1640. if i>2 then
  1641. raiseexception(format(Shhmmerror,[poffs+pind+1]));
  1642. timeval:=timeval+scanfixedint(2)* minfactor;
  1643. end
  1644. else
  1645. case lch of
  1646. 'H': timeval:=timeval+scanfixedint(2)* hrfactor;
  1647. 'D': begin
  1648. i:=scanpatlen;
  1649. case i of
  1650. 1,2 : dd:=scanfixedint(2);
  1651. 3 : dd:=findmatch(fmt.shortDayNames,s);
  1652. 4 : dd:=findmatch(fmt.longDayNames,s);
  1653. 5 : matchpattern(fmt.shortdateformat);
  1654. 6 : matchpattern(fmt.longdateformat);
  1655. end;
  1656. end;
  1657. 'N': timeval:=timeval+scanfixedint(2)* minfactor;
  1658. 'S': timeval:=timeval+scanfixedint(2)* secfactor;
  1659. 'Z': timeval:=timeval+scanfixedint(3)* mssecfactor;
  1660. 'Y': begin
  1661. i:=scanpatlen;
  1662. yy:=scanfixedint(i);
  1663. if i<=2 then
  1664. begin
  1665. pivot:=YearOf(now)-fmt.TwoDigitYearCenturyWindow;
  1666. inc(yy, pivot div 100 * 100);
  1667. if (fmt.TwoDigitYearCenturyWindow > 0) and (yy < pivot) then
  1668. inc(yy, 100);
  1669. end;
  1670. end;
  1671. 'M': begin
  1672. i:=scanpatlen;
  1673. case i of
  1674. 1,2: mm:=scanfixedint(2);
  1675. 3: mm:=findmatch(fmt.ShortMonthNames,s);
  1676. 4: mm:=findmatch(fmt.LongMonthNames,s);
  1677. end;
  1678. end;
  1679. 'T' : begin
  1680. i:=scanpatlen;
  1681. case i of
  1682. 1: matchpattern(fmt.shortdateformat);
  1683. 2: matchpattern(fmt.longtimeformat);
  1684. end;
  1685. end;
  1686. 'A' : begin
  1687. i:=findimatch(AMPMformatting,@ptrn[pind]);
  1688. case i of
  1689. 0: begin
  1690. i:=findimatch(['AM','PM'],@s[ind]);
  1691. case i of
  1692. 0: ;
  1693. 1: timeval:=timeval+12*hrfactor;
  1694. else
  1695. arraymatcherror
  1696. end;
  1697. inc(pind,length(AMPMformatting[0]));
  1698. inc(ind,2);
  1699. end;
  1700. 1: begin
  1701. case upcase(s[ind]) of
  1702. 'A' : ;
  1703. 'P' : timeval:=timeval+12*hrfactor;
  1704. else
  1705. arraymatcherror
  1706. end;
  1707. inc(pind,length(AMPMformatting[1]));
  1708. inc(ind);
  1709. end;
  1710. 2: begin
  1711. i:=findimatch([fmt.timeamstring,fmt.timepmstring],@s[ind]);
  1712. case i of
  1713. 0: inc(ind,length(fmt.timeamstring));
  1714. 1: begin
  1715. timeval:=timeval+12*hrfactor;
  1716. inc(ind,length(fmt.timepmstring));
  1717. end;
  1718. else
  1719. arraymatcherror
  1720. end;
  1721. inc(pind,length(AMPMformatting[2]));
  1722. inc(pind,2);
  1723. inc(ind,2);
  1724. end;
  1725. else // no AM/PM match. Assume 'a' is simply a char
  1726. matchchar(ptrn[pind]);
  1727. end;
  1728. end;
  1729. '/' : matchchar(fmt.dateSeparator);
  1730. ':' : begin
  1731. matchchar(fmt.TimeSeparator);
  1732. lch:=lasttoken;
  1733. end;
  1734. #39,'"' : begin
  1735. activequote:=lch;
  1736. inc(pind);
  1737. end;
  1738. 'C' : begin
  1739. intscandate(@fmt.shortdateformat[1],length(fmt.ShortDateFormat),pind+poffs);
  1740. intscandate(@fmt.longtimeformat[1],length(fmt.longtimeformat),pind+poffs);
  1741. inc(pind);
  1742. end;
  1743. '?' : begin
  1744. inc(pind);
  1745. inc(ind);
  1746. end;
  1747. #9 : begin
  1748. while (ind<=len) and (s[ind] in whitespace) do
  1749. inc(ind);
  1750. inc(pind);
  1751. end;
  1752. else
  1753. matchchar(ptrn[pind]);
  1754. end; {case}
  1755. lasttoken:=lch;
  1756. end
  1757. else
  1758. begin
  1759. if activequote=lch then
  1760. begin
  1761. activequote:=#0;
  1762. inc(pind);
  1763. end
  1764. else
  1765. matchchar(ptrn[pind]);
  1766. end;
  1767. end;
  1768. if (pind<plen) and (plen>0) and (ptrn[plen-1]<>#9) then // allow omission of trailing whitespace
  1769. RaiseException(format(SFullpattern,[poffs+pind+1]));
  1770. end;
  1771. var plen:integer;
  1772. begin
  1773. activequote:=#0;
  1774. yy:=0; mm:=0; dd:=0;
  1775. timeval:=0.0;
  1776. len:=length(s); ind:=startpos;
  1777. plen:=length(pattern);
  1778. intscandate(@pattern[1],plen,0);
  1779. result:=timeval;
  1780. if (yy>0) and (mm>0) and (dd>0) then
  1781. result:=result+encodedate(yy,mm,dd);
  1782. end;
  1783. function scandatetime(const pattern:string;const s:string;startpos:integer=1) : tdatetime; overload;
  1784. begin
  1785. result:=scandatetime(pattern,s,defaultformatsettings);
  1786. end;
  1787. {$else}
  1788. implementation
  1789. {$endif FPUNONE}
  1790. end.