source: Include/Classes/System/DateTime.ab@ 263

Last change on this file since 263 was 263, checked in by OverTaker, 17 years ago

#116のバグを修整。

File size: 13.7 KB
RevLine 
[36]1' Classes/System/DateTime.ab
2
3Class DateTime
4 m_Date As Int64
5Public
[209]6 Static MaxValue = 3162240000000000000 As Int64 'Const TicksPerDay*366*10000
7 Static MinValue = 316224000000000 As Int64 'Const TicksPerDay*366
[36]8
[163]9 Sub DateTime()
[209]10 initialize(MinValue, DateTimeKind.Unspecified)
[163]11 End Sub
12
[36]13 Sub DateTime(ticks As Int64)
[209]14 initialize(ticks, DateTimeKind.Unspecified)
[36]15 End Sub
16
17 Sub DateTime(ticks As Int64, kind As DateTimeKind)
[209]18 initialize(ticks, kind)
[36]19 End Sub
20
21 Sub DateTime(year As Long, month As Long, day As Long)
[209]22 initialize(year, month, day, 0, 0, 0, 0, DateTimeKind.Unspecified)
[36]23 End Sub
24
25 Sub DateTime(year As Long, month As Long, day As Long, kind As DateTimeKind)
[209]26 initialize(year, month, day, 0, 0, 0, 0, kind)
[36]27 End Sub
28
29 Sub DateTime(year As Long, month As Long, day As Long, hour As Long, minute As Long, second As Long)
[209]30 initialize(year, month, day, hour, minute, second, 0, DateTimeKind.Unspecified)
[36]31 End Sub
32
[103]33 Sub DateTime(year As Long, month As Long, day As Long, hour As Long, minute As Long, second As Long, kind As DateTimeKind)
[209]34 initialize(year, month, day, hour, minute, second, 0, kind)
[103]35 End Sub
[36]36
37 Sub DateTime(year As Long, month As Long, day As Long, hour As Long, minute As Long, second As Long, millisecond As Long)
[209]38 initialize(year, month, day, hour, minute, second, millisecond, DateTimeKind.Unspecified)
[36]39 End Sub
40
41 Sub DateTime(year As Long, month As Long, day As Long, hour As Long, minute As Long, second As Long, millisecond As Long, kind As DateTimeKind)
[209]42 initialize(year, month, day, hour, minute, second, millisecond, kind)
[36]43 End Sub
44
45 Sub DateTime(ByRef time As SYSTEMTIME)
[209]46 initialize(time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds, DateTimeKind.Unspecified)
[36]47 End Sub
48
49 Sub DateTime(ByRef time As SYSTEMTIME, kind As DateTimeKind)
[209]50 initialize(time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, time.wSecond, time.wMilliseconds, kind)
[36]51 End Sub
52
[40]53 'Copy Constructor
[209]54 Sub DateTime(ByRef dateTime As DateTime)
55 This.m_Date = dateTime.m_Date
[40]56 End Sub
57
[36]58 Sub ~DateTime()
59 End Sub
60
[166]61 Function Operator + (ByRef value As TimeSpan) As DateTime
[209]62 Return New DateTime(Ticks + value.Ticks)
[107]63 End Function
64
[166]65 Function Operator - (ByRef value As DateTime) As TimeSpan
[107]66 Return TimeSpan.FromTicks(Ticks - value.Ticks)
67 End Function
68
[166]69 Function Operator - (ByRef value As TimeSpan) As DateTime
[209]70 Return New DateTime(Ticks - value.Ticks)
[107]71 End Function
72
[93]73 Function Operator == (ByRef value As DateTime) As Boolean
[36]74 Return Equals(value)
75 End Function
76
[93]77 Function Operator <> (ByRef value As DateTime) As Boolean
[36]78 Return Not Equals(value)
79 End Function
80
[93]81 Function Operator > (ByRef value As DateTime) As Boolean
[36]82 If DateTime.Compare(This, value) > 0 Then
[93]83 Return True
[36]84 Else
[93]85 Return False
[36]86 End If
87 End Function
88
[93]89 Function Operator < (ByRef value As DateTime) As Boolean
[36]90 If DateTime.Compare(This, value) < 0 Then
[93]91 Return True
[36]92 Else
[93]93 Return False
[36]94 End If
95 End Function
96
[93]97 Function Operator >= (ByRef value As DateTime) As Boolean
[36]98 If DateTime.Compare(This, value) => 0 Then
[93]99 Return True
[36]100 Else
[93]101 Return False
[36]102 End If
103 End Function
104
[93]105 Function Operator <= (ByRef value As DateTime) As Boolean
[36]106 If DateTime.Compare(This, value) <= 0 Then
[93]107 Return True
[36]108 Else
[93]109 Return False
[36]110 End If
111 End Function
112
[209]113 'Public Properties
[36]114 Function Ticks() As Int64
115 Return (m_Date And &H3FFFFFFFFFFFFFFF)
116 End Function
117
118 Function Millisecond() As Long
[107]119 Return (Ticks \ TimeSpan.TicksPerMillisecond Mod 1000) As Long
[36]120 End Function
121
122 Function Second() As Long
[107]123 Return (Ticks \ TimeSpan.TicksPerSecond Mod 60) As Long
[36]124 End Function
125
126 Function Minute() As Long
[107]127 Return (Ticks \ TimeSpan.TicksPerMinute Mod 60) As Long
[36]128 End Function
129
130 Function Hour() As Long
[107]131 Return (Ticks \ TimeSpan.TicksPerHour Mod 24) As Long
[36]132 End Function
133
134 Function Day() As Long
[263]135 Return DayOfYear - totalDaysOfMonth(Year, Month - 1)
[36]136 End Function
137
138 Function Month() As Long
[209]139 Dim year = Year As Long
140 Dim day = DayOfYear As Long
141 Dim i = 1 As Long
[263]142 While day > totalDaysOfMonth(year, i)
[209]143 i++
144 Wend
145 Return i
[36]146 End Function
147
148 Function Year() As Long
[209]149 Dim day = (Ticks \ TimeSpan.TicksPerDay) As Long
[263]150 Dim year = Int((day + day \ 36524 - day \ 146097) / 365.25) + 1 As Long
151 If day - yearToDay(year - 1) + 1 = 366 Then
[209]152 Return year + 1
153 Else
154 Return year
155 End If
[36]156 End Function
157
[209]158 Function DayOfWeek() As Long 'As DayOfWeek
[263]159 Return ((Ticks \ TimeSpan.TicksPerDay) Mod 7) As Long + 1
[36]160 End Function
161
[81]162 Function Kind() As DateTimeKind
[36]163 Return kindFromBinary(m_Date)
164 End Function
165
166 Function DayOfYear() As Long
[263]167 Return ((Ticks \ TimeSpan.TicksPerDay) - yearToDay(Year) + 1) As Long
[36]168 End Function
169
170 Function Date() As DateTime
[209]171 Return New DateTime(Year, Month, Day, Kind)
[36]172 End Function
173
174 Static Function Now() As DateTime
175 Dim time As SYSTEMTIME
176 GetLocalTime(time)
[209]177 Return New DateTime(time, DateTimeKind.Local)
[36]178 End Function
179
180 Static Function ToDay() As DateTime
181 Dim time As SYSTEMTIME
182 GetLocalTime(time)
[209]183 Return New DateTime(time.wYear, time.wMonth, time.wDay, DateTimeKind.Local)
[36]184 End Function
185
186 Static Function UtcNow() As DateTime
187 Dim time As SYSTEMTIME
188 GetSystemTime(time)
[209]189 Return New DateTime(time, DateTimeKind.Utc)
[36]190 End Function
191
[209]192 'Public Methods
[36]193 Static Function Compare(ByRef t1 As DateTime, ByRef t2 As DateTime) As Int64
194 Return t1.Ticks - t2.Ticks
195 End Function
196
[93]197 Function Equals(ByRef value As DateTime) As Boolean
[36]198 If value.m_Date = m_Date Then
[93]199 Return True
[36]200 Else
[93]201 Return False
[36]202 End If
203 End Function
204
[93]205 Static Function Equals(ByRef t1 As DateTime, ByRef t2 As DateTime) As Boolean
[36]206 If t1.m_Date = t2.m_Date Then
[93]207 Return True
[36]208 Else
[93]209 Return False
[36]210 End If
211 End Function
212
[166]213 Override Function GetHashCode() As Long
214 Return HIDWORD(m_Date) Xor LODWORD(m_Date)
215 End Function
216
[107]217 Function Add(ByRef value As TimeSpan) As DateTime
218 Return This + value
219 End Function
220
221 Function AddTicks(value As Int64) As DateTime
[209]222 Return New DateTime(Ticks + value, Kind )
[107]223 End Function
[36]224
[107]225 Function AddMilliseconds(value As Double) As DateTime
226 Return AddTicks((value * TimeSpan.TicksPerMillisecond) As Int64)
227 End Function
[36]228
[107]229 Function AddSeconds(value As Double) As DateTime
230 Return AddTicks((value * TimeSpan.TicksPerSecond) As Int64)
231 End Function
[36]232
[107]233 Function AddMinutes(value As Double) As DateTime
234 Return AddTicks((value * TimeSpan.TicksPerMinute) As Int64)
235 End Function
[36]236
[107]237 Function AddHours(value As Double) As DateTime
238 Return AddTicks((value * TimeSpan.TicksPerHour) As Int64)
239 End Function
[36]240
[107]241 Function AddDays(value As Double) As DateTime
242 Return AddTicks((value * TimeSpan.TicksPerDay) As Int64)
243 End Function
244
245 Function AddYears(value As Double) As DateTime
[263]246 Dim date = New DateTime(Year + Int(value), Month, Day, Hour, Minute, Second, Millisecond, Kind)
247 Dim ticks = Ticks _
248 - (yearToDay(Year) + totalDaysOfMonth(Year, Month - 1) + Day - 1) * TimeSpan.TicksPerDay _
249 - Hour * TimeSpan.TicksPerHour _
250 - Minute * TimeSpan.TicksPerMinute _
251 - Second * TimeSpan.TicksPerSecond _
252 - Millisecond * TimeSpan.TicksPerMillisecond As Int64
253 If IsLeapYear(Year + Int(value)) Then
[209]254 ticks += (value - Int(value)) * 366 * TimeSpan.TicksPerDay
[36]255 Else
[209]256 ticks += (value - Int(value)) * 365 * TimeSpan.TicksPerDay
[36]257 End If
[263]258 Return date.AddTicks(ticks)
[107]259 End Function
[36]260
[107]261 Function Subtract(ByRef value As DateTime) As TimeSpan
[209]262 Return New DateTime(This - value)
[107]263 End Function
264
265 Function Subtract(ByRef value As TimeSpan) As DateTime
[209]266 Return New DateTime(This - value)
[107]267 End Function
268
[93]269 Static Function DaysInMonth(year As Long, month As Long) As Long
[36]270 If year < 1 Or year > 9999 Or month < 1 Or month > 12 Then
271 'ArgumentOutOfRangeException
272 debug
273 End If
[209]274
[93]275 If IsLeapYear(year) And month = 2 Then
276 Return 29
277 Else
278 Dim daysInMonth[11] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] As Byte
279 Return daysInMonth[month - 1]
280 End If
[36]281 End Function
282
[93]283 Static Function IsLeapYear(year As Long) As Boolean
284 If (year Mod 400) = 0 Then Return True
285 If (year Mod 100) = 0 Then Return False
286 If (year Mod 4) = 0 Then Return True
[103]287 Return False
[36]288 End Function
289
290 Function GetDateTimeFormats() As String
[209]291 Dim time = getSystemTime() 'As SYSTEMTIME を記述すると内部エラーが発生
292 Dim dateFormatSize = GetDateFormat(LOCALE_USER_DEFAULT, 0, time, NULL, NULL, 0)
293 Dim timeFormatSize = GetTimeFormat(LOCALE_USER_DEFAULT, 0, time, NULL, NULL, 0)
294 Dim dateTimeFormats = malloc(dateFormatSize + timeFormatSize) As PTSTR
295 GetDateFormat(LOCALE_USER_DEFAULT, 0, time, NULL, dateTimeFormats, dateFormatSize)
296 dateTimeFormats[dateFormatSize - 1] = Asc(" ")
297 GetTimeFormat(LOCALE_USER_DEFAULT, 0, time, NULL, dateTimeFormats + dateFormatSize, timeFormatSize)
298
299 Return New String(dateTimeFormats)
[36]300 End Function
301
[209]302 Function GetDateTimeFormats(format As *TCHAR) As String
303 Dim time = getSystemTime() 'As SYSTEMTIME を記述すると内部エラーが発生
304 Dim dateFormatSize = GetDateFormat(LOCALE_USER_DEFAULT, 0, time, format, NULL, 0)
305 Dim dateFormats = malloc(dateFormatSize) As PTSTR
306 GetDateFormat(LOCALE_USER_DEFAULT, 0, time, format, dateFormats, dateFormatSize)
[73]307
[209]308 Dim dateTimeFormatSize = GetTimeFormat(LOCALE_USER_DEFAULT, 0, time, dateFormats, NULL, 0)
309 Dim dateTimeFormats = malloc(dateTimeFormatSize) As PTSTR
310 GetTimeFormat(LOCALE_USER_DEFAULT, 0, time, dateFormats, dateTimeFormats, dateTimeFormatSize)
[207]311
[209]312 Return New String(dateTimeFormats)
[73]313 End Function
314
[209]315 Static Function FromBinary(date As Int64) As DateTime
316 Return New DateTime((date And &H3FFFFFFFFFFFFFFF), kindFromBinary(date))
[36]317 End Function
318
319 Function ToBinary() As Int64
320 Return m_Date
321 End Function
322
[209]323 Static Function FromFileTime(ByRef fileTime As FILETIME) As DateTime
[36]324 Dim localTime As FILETIME
[82]325 Dim time As SYSTEMTIME
[36]326 FileTimeToLocalFileTime(fileTime, localTime)
327 FileTimeToSystemTime(localTime, time)
[209]328 Return New DateTime(time, DateTimeKind.Local)
[36]329 End Function
330
331 Function ToFileTime() As FILETIME
[209]332 Dim time = getSystemTime() 'As SYSTEMTIME を記述すると内部エラーが発生 rev.207
[36]333 Dim fileTime As FILETIME
334 SystemTimeToFileTime(time, fileTime)
335 Return fileTime
336 End Function
337
[209]338 Static Function FromFileTimeUtc(ByRef fileTime As FILETIME) As DateTime
[36]339 Dim time As SYSTEMTIME
340 FileTimeToSystemTime(fileTime, time)
[209]341 Return New DateTime(time, DateTimeKind.Utc)
[36]342 End Function
343
344 Function ToFileTimeUtc() As FILETIME
[209]345 Dim fileTime = ToFileTime() 'As FILETIME を記述すると内部エラー rev.207
[103]346 If Kind = DateTimeKind.Utc Then
[209]347 Return fileTime
[36]348 Else
[209]349 Dim utcTime As FILETIME
350 LocalFileTimeToFileTime(fileTime, utcTime)
351 Return utcTime
[36]352 End If
353 End Function
354
355 Function ToLocalTime() As DateTime
[103]356 If Kind = DateTimeKind.Local Then
[209]357 Return New DateTime(This)
[82]358 Else
[209]359 Dim fileTime = ToFileTime() '直接入れると計算できなくなります。 rev.207
360 Return DateTime.FromFileTime(fileTime)
[81]361 End If
[36]362 End Function
[81]363
[228]364 Override Function ToString() As String
365 Return GetDateTimeFormats()
366 End Function
367
[81]368 Function ToUniversalTime() As DateTime
[103]369 If Kind = DateTimeKind.Utc Then
[209]370 Return New DateTime(m_Date)
[82]371 Else
[209]372 Dim fileTime = ToFileTimeUtc() '直接入れると計算できなくなります。 rev.207
373 Return DateTime.FromFileTimeUtc(fileTime)
[81]374 End If
375 End Function
[209]376
[36]377Private
[209]378 Sub initialize(ticks As Int64, kind As DateTimeKind)
379 Kind = kind
380 Ticks = ticks
381 End Sub
382
383 Sub initialize(year As Long, month As Long, day As Long, hour As Long, minute As Long, second As Long, millisecond As Long, kind As DateTimeKind)
384 If month < 1 Or month > 12 _
385 Or day < 1 Or day > DaysInMonth(year, month) _
386 Or hour < 0 Or hour => 24 _
387 Or minute < 0 Or minute => 60 _
388 Or second < 0 Or second => 60 _
389 Or millisecond < 0 Or millisecond => 1000 Then
390 debug 'ArgumentOutOfRangeException
391 End If
392
393 initialize(
[263]394 yearToDay(year) * TimeSpan.TicksPerDay _
395 + totalDaysOfMonth(year, month - 1) * TimeSpan.TicksPerDay _
[209]396 + (day - 1) * TimeSpan.TicksPerDay _
397 + hour * TimeSpan.TicksPerHour _
398 + minute * TimeSpan.TicksPerMinute _
399 + second * TimeSpan.TicksPerSecond _
400 + millisecond * TimeSpan.TicksPerMillisecond,
401 kind
402 )
403 End Sub
404
[36]405 Sub Ticks(value As Int64)
[209]406 If value < MinValue Or value > MaxValue Then
407 debug 'ArgumentOutOfRangeException
408 End If
409
410 Dim temp = Kind As DateTimeKind
[36]411 m_Date = value
[209]412 Kind = temp
[36]413 End Sub
414
415 Sub Kind(kind As DateTimeKind)
416 Dim temp As Int64
417 temp = kind
418 temp = (temp << 62) And &HC000000000000000
419 m_Date = (m_Date And &H3FFFFFFFFFFFFFFF) Or temp
420 End Sub
421
[209]422 Static Function kindFromBinary(date As Int64) As DateTimeKind
423 date = (date >> 62) And &H03
424 If date = &H01 Then
[103]425 Return DateTimeKind.Local
[209]426 ElseIf date = &H02 Then
[103]427 Return DateTimeKind.Unspecified
[209]428 ElseIf date = &H03 Then
[103]429 Return DateTimeKind.Utc
[36]430 End If
[246]431
432 ' ここにはこないはず
433 debug
[36]434 End Function
[209]435
436 Function getSystemTime() As SYSTEMTIME
437 Dim time As SYSTEMTIME
438 With time
439 .wYear = Year As Word
440 .wMonth = Month As Word
441 .wDayOfWeek = DayOfWeek As Word
442 .wDay = Day As Word
443 .wHour = Hour As Word
444 .wMinute = Minute As Word
445 .wSecond = Second As Word
446 .wMilliseconds = Millisecond As Word
447 End With
448 Return time
449 End Function
450
[263]451 Static Function yearToDay(year As Long) As Long
452 year--
[209]453 Return (Int(year * 365.25) - Int(year * 0.01) + Int(year * 0.0025))
454 End Function
455
[263]456 Static Function totalDaysOfMonth(year As Long, month As Long) As Long
[209]457 Dim days As Long
458 Dim i As Long
459 For i = 1 To month
460 days += DaysInMonth(year, i)
461 Next
462 Return days
463 End Function
[36]464End Class
465
[103]466Enum DateTimeKind
[36]467 Local
468 Unspecified
469 Utc
470End Enum
471
[103]472Enum DayOfWeek
[36]473 Sunday = 0
474 Monday
475 Tuesday
476 Wednesday
477 Thursday
478 Friday
479 Saturday
[209]480End Enum
Note: See TracBrowser for help on using the repository browser.