@@ -22,14 +22,20 @@ local trunc = System.trunc
2222local TimeSpan = System .TimeSpan
2323local ArgumentOutOfRangeException = System .ArgumentOutOfRangeException
2424local ArgumentException = System .ArgumentException
25+ local ArgumentNullException = System .ArgumentNullException
26+ local FormatException = System .FormatException
2527
2628local getmetatable = getmetatable
2729local select = select
28- local format = string.format
30+ local sformat = string.format
31+ local sfind = string.find
2932local os = os
3033local ostime = os.time
3134local osdifftime = os.difftime
3235local osdate = os.date
36+ local tonumber = tonumber
37+ local floor = math.floor
38+ local log10 = math.log10
3339
3440-- http://referencesource.microsoft.com/#mscorlib/system/datetime.cs
3541local DateTime = {}
@@ -103,26 +109,31 @@ local function checkTicks(ticks)
103109end
104110
105111local function checkKind (kind )
106- if kind and ( kind < 0 or kind > 2 ) then
112+ if kind < 0 or kind > 2 then
107113 throw (ArgumentOutOfRangeException (" kind" ))
108114 end
109115end
110116
111117function DateTime .__ctor__ (this , ...)
112118 local len = select (" #" , ... )
113- if len == 1 or len == 2 then
119+ if len == 1 then
120+ local ticks = ...
121+ checkTicks (ticks )
122+ this .ticks = ticks
123+ elseif len == 2 then
114124 local ticks , kind = ...
115125 checkTicks (ticks )
116126 checkKind (kind )
117127 this .ticks = ticks
118128 this .kind = kind
119129 elseif len == 3 then
120130 this .ticks = dateToTicks (... )
121- elseif len == 6 or len == 7 then
122- local year , month , day , hour , minute , second , kind = ...
123- checkKind (kind )
131+ elseif len == 6 then
132+ local year , month , day , hour , minute , second = ...
124133 this .ticks = dateToTicks (year , month , day ) + timeToTicks (hour , minute , second )
125- this .kind = kind
134+ elseif len == 7 then
135+ local year , month , day , hour , minute , second , millisecond = ...
136+ this .ticks = dateToTicks (year , month , day ) + timeToTicks (hour , minute , second ) + millisecond * 1e4
126137 elseif len == 8 then
127138 local year , month , day , hour , minute , second , millisecond , kind = ...
128139 checkKind (kind )
@@ -354,9 +365,81 @@ function DateTime.ToUniversalTime(this)
354365end
355366
356367function DateTime .ToString (this )
357- return format (" %d/%d/%d %02d:%02d:%02d.%03d" ,
358- this :getYear (), this :getMonth (), this :getDay (),
359- this :getHour (), this :getMinute (), this :getSecond (), this :getMillisecond ())
368+ local year , month , day = getDatePart (this .ticks )
369+ return sformat (" %d/%d/%d %02d:%02d:%02d" , year , month , day , this :getHour (), this :getMinute (), this :getSecond ())
370+ end
371+
372+ local function parse (s )
373+ if s == nil then
374+ return nil , 1
375+ end
376+ local i , j , year , month , day , hour , minute , second , milliseconds
377+ i , j , year , month , day = sfind (s , " ^%s*(%d+)%s*/%s*(%d+)%s*/%s*(%d+)%s*" )
378+ if i == nil then
379+ return nil , 2
380+ else
381+ year , month , day = tonumber (year ), tonumber (month ), tonumber (day )
382+ end
383+ if j < # s then
384+ i , j , hour , minute = sfind (s , " ^(%d+)%s*:%s*(%d+)" , j + 1 )
385+ if i == nil then
386+ return nil , 2
387+ else
388+ hour , minute = tonumber (hour ), tonumber (minute )
389+ end
390+ local next = j + 1
391+ i , j , second = sfind (s , " ^:%s*(%d+)" , next )
392+ if i == nil then
393+ if sfind (s , " ^%s*$" , next ) == nil then
394+ return nil , 2
395+ else
396+ second = 0
397+ milliseconds = 0
398+ end
399+ else
400+ second = tonumber (second )
401+ next = j + 1
402+ i , j , milliseconds = sfind (s , " ^%.(%d+)%s*$" , next )
403+ if i == nil then
404+ if sfind (s , " ^%s*$" , next ) == nil then
405+ return nil , 2
406+ else
407+ milliseconds = 0
408+ end
409+ else
410+ milliseconds = tonumber (milliseconds )
411+ local n = floor (log10 (milliseconds ) + 1 )
412+ if n > 3 then
413+ if n < 7 then
414+ milliseconds = milliseconds / (10 ^ (n - 3 ))
415+ else
416+ local ticks = milliseconds / (10 ^ (n - 7 ))
417+ local _ , decimal = math.modf (ticks )
418+ if decimal > 0.5 then
419+ ticks = ticks + 1
420+ end
421+ milliseconds = floor (ticks ) / 1e4
422+ end
423+ end
424+ end
425+ end
426+ end
427+ if hour == nil then
428+ return DateTime (year , month , day )
429+ end
430+ return DateTime (year , month , day , hour , minute , second , milliseconds )
431+ end
432+
433+ function DateTime .Parse (s )
434+ local v , err = parse (s )
435+ if v then
436+ return v
437+ end
438+ if err == 1 then
439+ throw (ArgumentNullException ())
440+ else
441+ throw (FormatException ())
442+ end
360443end
361444
362445DateTime .__add = DateTime .Add
@@ -387,3 +470,11 @@ DateTime.MaxValue = DateTime(3155378975999999999)
387470function DateTime .__default__ ()
388471 return minValue
389472end
473+
474+ function DateTime .TryParse (s )
475+ local v = parse (s )
476+ if v then
477+ return true , v
478+ end
479+ return false , minValue
480+ end
0 commit comments