Skip to content

Commit c0ee502

Browse files
committed
implement DateTime.Parse & TimeSpan.Parse
1 parent f3bf0f4 commit c0ee502

3 files changed

Lines changed: 227 additions & 16 deletions

File tree

‎CSharp.lua/CoreSystem.Lua/CoreSystem/DateTime.lua‎

Lines changed: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,20 @@ local trunc = System.trunc
2222
local TimeSpan = System.TimeSpan
2323
local ArgumentOutOfRangeException = System.ArgumentOutOfRangeException
2424
local ArgumentException = System.ArgumentException
25+
local ArgumentNullException = System.ArgumentNullException
26+
local FormatException = System.FormatException
2527

2628
local getmetatable = getmetatable
2729
local select = select
28-
local format = string.format
30+
local sformat = string.format
31+
local sfind = string.find
2932
local os = os
3033
local ostime = os.time
3134
local osdifftime = os.difftime
3235
local 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
3541
local DateTime = {}
@@ -103,26 +109,31 @@ local function checkTicks(ticks)
103109
end
104110

105111
local 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
109115
end
110116

111117
function 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)
354365
end
355366

356367
function 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
360443
end
361444

362445
DateTime.__add = DateTime.Add
@@ -387,3 +470,11 @@ DateTime.MaxValue = DateTime(3155378975999999999)
387470
function DateTime.__default__()
388471
return minValue
389472
end
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

‎CSharp.lua/CoreSystem.Lua/CoreSystem/TimeSpan.lua‎

Lines changed: 94 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,17 @@ local div = System.div
2020
local trunc = System.trunc
2121
local ArgumentException = System.ArgumentException
2222
local OverflowException = System.OverflowException
23+
local ArgumentNullException = System.ArgumentNullException
24+
local FormatException = System.FormatException
2325

2426
local getmetatable = getmetatable
2527
local select = select
26-
local format = string.format
28+
local sformat = string.format
29+
local sfind = string.find
2730
local tostring = tostring
31+
local tonumber = tonumber
32+
local floor = math.floor
33+
local log10 = math.log10
2834

2935
local TimeSpan = {}
3036

@@ -148,9 +154,84 @@ function TimeSpan.Negate(this)
148154
end
149155

150156
function TimeSpan.ToString(this)
151-
local day = this:getDays()
152-
local daysStr = day == 0 and "" or (tostring(day) .. ".")
153-
return format("%s%02d:%02d:%02d.%03d", daysStr, this:getHours(), this:getMinutes(), this:getSeconds(), this:getMilliseconds())
157+
local day, milliseconds = this:getDays(), this.ticks % 1e7
158+
local daysStr = day == 0 and "" or (day .. ".")
159+
local millisecondsStr = milliseconds == 0 and "" or "." .. milliseconds
160+
return sformat("%s%02d:%02d:%02d%s", daysStr, this:getHours(), this:getMinutes(), this:getSeconds(), millisecondsStr)
161+
end
162+
163+
local function parse(s)
164+
if s == nil then
165+
return nil, 1
166+
end
167+
local v = tonumber(s)
168+
if v ~= nil then
169+
if v ~= floor(v) then
170+
return nil, 2
171+
end
172+
return TimeSpan.FromDays(v)
173+
end
174+
local i, j, day, hour, minute, second, milliseconds
175+
i, j, day, hour, minute = sfind(s, "^%s*(%d+)%.(%d+):(%d+)")
176+
if i == nil then
177+
i, j, hour, minute = sfind(s, "^%s*(%d+):(%d+)")
178+
if i == nil then
179+
return nil, 2
180+
else
181+
hour, minute = tonumber(hour), tonumber(minute)
182+
end
183+
day = 0
184+
else
185+
day, hour, minute = tonumber(day), tonumber(hour), tonumber(minute)
186+
end
187+
if j < #s then
188+
local next = j + 1
189+
i, j, second = sfind(s, "^:(%d+)", next)
190+
if i == nil then
191+
if sfind(s, "^%s*$", next) == nil then
192+
return nil, 2
193+
else
194+
second = 0
195+
milliseconds = 0
196+
end
197+
else
198+
second = tonumber(second)
199+
next = j + 1
200+
i, j, milliseconds = sfind(s, "^%.(%d+)%s*$", next)
201+
if i == nil then
202+
if sfind(s, "^%s*$", next) == nil then
203+
return nil, 2
204+
else
205+
milliseconds = 0
206+
end
207+
else
208+
milliseconds = tonumber(milliseconds)
209+
local n = floor(log10(milliseconds) + 1)
210+
if n > 3 then
211+
if n > 7 then
212+
return nil, 2
213+
end
214+
milliseconds = milliseconds / (10 ^ (n - 3))
215+
end
216+
end
217+
end
218+
else
219+
second = 0
220+
milliseconds = 0
221+
end
222+
return TimeSpan(day, hour, minute, second, milliseconds)
223+
end
224+
225+
function TimeSpan.Parse(s)
226+
local v, err = parse(s)
227+
if v then
228+
return v
229+
end
230+
if err == 1 then
231+
throw(ArgumentNullException())
232+
else
233+
throw(FormatException())
234+
end
154235
end
155236

156237
TimeSpan.__add = TimeSpan.Add
@@ -217,4 +298,12 @@ TimeSpan.MinValue = TimeSpan(-9223372036854775808)
217298

218299
function TimeSpan.__default__()
219300
return zero
220-
end
301+
end
302+
303+
function TimeSpan.TryParse(s)
304+
local v = parse(s)
305+
if v then
306+
return true, v
307+
end
308+
return false, zero
309+
end

‎CSharp.lua/System.xml‎

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,38 @@ limitations under the License.
7070
<method name="TryParse" ArgCount="3" Template="System.Enum.TryParse({^0}, {0}, {1})" />
7171
<method name="ToString" Template="{this}:ToEnumString({class})" />
7272
</class>
73+
<class name="DateTime">
74+
<method name=".ctor" ArgCount="4" Baned="true" />
75+
<method name=".ctor" Baned="true">
76+
<arg type="System.Int32" />
77+
<arg type="System.Int32" />
78+
<arg type="System.Int32" />
79+
<arg type="System.Int32" />
80+
<arg type="System.Int32" />
81+
<arg type="System.Int32" />
82+
<arg type="System.Globalization.Calendar" />
83+
</method>
84+
<method name=".ctor" Baned="true">
85+
<arg type="System.Int32" />
86+
<arg type="System.Int32" />
87+
<arg type="System.Int32" />
88+
<arg type="System.Int32" />
89+
<arg type="System.Int32" />
90+
<arg type="System.Int32" />
91+
<arg type="System.Int32" />
92+
<arg type="System.Globalization.Calendar" />
93+
</method>
94+
<method name=".ctor" ArgCount="9" Baned="true" />
95+
<method name=".ctor" Template="System.DateTime({0}, {1}, {2}, {3}, {4}, {5}, 0, {6})">
96+
<arg type="System.Int32" />
97+
<arg type="System.Int32" />
98+
<arg type="System.Int32" />
99+
<arg type="System.Int32" />
100+
<arg type="System.Int32" />
101+
<arg type="System.Int32" />
102+
<arg type="System.DateTimeKind" />
103+
</method>
104+
</class>
73105
<class name="Object">
74106
<method name="Equals" Name="EqualsObj" >
75107
<arg type="System.Object" />
@@ -115,7 +147,6 @@ limitations under the License.
115147
<arg type="System.Char" />
116148
</method>
117149
</class>
118-
<class name="Math" Name="math" />
119150
<class name="Activator" >
120151
<method name="CreateInstance" ArgCount="0" Template="System.new({^0})" />
121152
<method name="CreateInstance" ArgCount="1" Template="System.new({0}.c)" />

0 commit comments

Comments
 (0)