dateutil.inc 71 KB

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