dateutil.inc 70 KB

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