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

Last change on this file since 272 was 272, checked in by イグトランス (egtra), 17 years ago

StringBuilderを追加。String不変へ。共通の文字列操作関数をActiveBasic.Strings内に配置(設計に検討の余地あり)。

File size: 13.6 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
[268]54 Sub DateTime(dateTime As DateTime)
[209]55 This.m_Date = dateTime.m_Date
[40]56 End Sub
57
[36]58 Sub ~DateTime()
59 End Sub
60
[268]61 Function Operator + (value As TimeSpan) As DateTime
[209]62 Return New DateTime(Ticks + value.Ticks)
[107]63 End Function
64
[268]65 Function Operator - (value As DateTime) As TimeSpan
[107]66 Return TimeSpan.FromTicks(Ticks - value.Ticks)
67 End Function
68
[268]69 Function Operator - (value As TimeSpan) As DateTime
[209]70 Return New DateTime(Ticks - value.Ticks)
[107]71 End Function
72
[268]73 Function Operator == (value As DateTime) As Boolean
[36]74 Return Equals(value)
75 End Function
76
[268]77 Function Operator <> (value As DateTime) As Boolean
[36]78 Return Not Equals(value)
79 End Function
80
[268]81 Function Operator > (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
[268]89 Function Operator < (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
[268]97 Function Operator >= (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
[268]105 Function Operator <= (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
[272]180 Static Function Today() As DateTime
[36]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
[268]193 Static Function Compare(t1 As DateTime, t2 As DateTime) As Int64
[36]194 Return t1.Ticks - t2.Ticks
195 End Function
196
[268]197 Function Equals(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
[268]205 Static Function Equals(t1 As DateTime, 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
[268]217 Function Add(value As TimeSpan) As DateTime
[107]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
[268]261 Function Subtract(value As DateTime) As TimeSpan
262 Return This - value
[107]263 End Function
264
[268]265 Function Subtract(value As TimeSpan) As DateTime
266 Return 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)
[272]294 Dim strLength = dateFormatSize + timeFormatSize
295 Dim dateTimeFormats = GC_malloc_atomic(SizeOf (TCHAR) * (strLength)) As PTSTR
[209]296 GetDateFormat(LOCALE_USER_DEFAULT, 0, time, NULL, dateTimeFormats, dateFormatSize)
297 dateTimeFormats[dateFormatSize - 1] = Asc(" ")
298 GetTimeFormat(LOCALE_USER_DEFAULT, 0, time, NULL, dateTimeFormats + dateFormatSize, timeFormatSize)
[272]299'Debug
300 Return New String(dateTimeFormats, strLength)
[36]301 End Function
302
[209]303 Function GetDateTimeFormats(format As *TCHAR) As String
304 Dim time = getSystemTime() 'As SYSTEMTIME を記述すると内部エラーが発生
305 Dim dateFormatSize = GetDateFormat(LOCALE_USER_DEFAULT, 0, time, format, NULL, 0)
306 Dim dateFormats = malloc(dateFormatSize) As PTSTR
307 GetDateFormat(LOCALE_USER_DEFAULT, 0, time, format, dateFormats, dateFormatSize)
[73]308
[209]309 Dim dateTimeFormatSize = GetTimeFormat(LOCALE_USER_DEFAULT, 0, time, dateFormats, NULL, 0)
310 Dim dateTimeFormats = malloc(dateTimeFormatSize) As PTSTR
311 GetTimeFormat(LOCALE_USER_DEFAULT, 0, time, dateFormats, dateTimeFormats, dateTimeFormatSize)
[207]312
[209]313 Return New String(dateTimeFormats)
[73]314 End Function
315
[209]316 Static Function FromBinary(date As Int64) As DateTime
317 Return New DateTime((date And &H3FFFFFFFFFFFFFFF), kindFromBinary(date))
[36]318 End Function
319
320 Function ToBinary() As Int64
321 Return m_Date
322 End Function
323
[209]324 Static Function FromFileTime(ByRef fileTime As FILETIME) As DateTime
[36]325 Dim localTime As FILETIME
[82]326 Dim time As SYSTEMTIME
[36]327 FileTimeToLocalFileTime(fileTime, localTime)
328 FileTimeToSystemTime(localTime, time)
[209]329 Return New DateTime(time, DateTimeKind.Local)
[36]330 End Function
331
332 Function ToFileTime() As FILETIME
[209]333 Dim time = getSystemTime() 'As SYSTEMTIME を記述すると内部エラーが発生 rev.207
[36]334 Dim fileTime As FILETIME
335 SystemTimeToFileTime(time, fileTime)
336 Return fileTime
337 End Function
338
[209]339 Static Function FromFileTimeUtc(ByRef fileTime As FILETIME) As DateTime
[36]340 Dim time As SYSTEMTIME
341 FileTimeToSystemTime(fileTime, time)
[209]342 Return New DateTime(time, DateTimeKind.Utc)
[36]343 End Function
344
345 Function ToFileTimeUtc() As FILETIME
[209]346 Dim fileTime = ToFileTime() 'As FILETIME を記述すると内部エラー rev.207
[103]347 If Kind = DateTimeKind.Utc Then
[209]348 Return fileTime
[36]349 Else
[209]350 Dim utcTime As FILETIME
351 LocalFileTimeToFileTime(fileTime, utcTime)
352 Return utcTime
[36]353 End If
354 End Function
355
356 Function ToLocalTime() As DateTime
[103]357 If Kind = DateTimeKind.Local Then
[209]358 Return New DateTime(This)
[82]359 Else
[209]360 Dim fileTime = ToFileTime() '直接入れると計算できなくなります。 rev.207
361 Return DateTime.FromFileTime(fileTime)
[81]362 End If
[36]363 End Function
[81]364
[228]365 Override Function ToString() As String
366 Return GetDateTimeFormats()
367 End Function
368
[81]369 Function ToUniversalTime() As DateTime
[103]370 If Kind = DateTimeKind.Utc Then
[209]371 Return New DateTime(m_Date)
[82]372 Else
[209]373 Dim fileTime = ToFileTimeUtc() '直接入れると計算できなくなります。 rev.207
374 Return DateTime.FromFileTimeUtc(fileTime)
[81]375 End If
376 End Function
[209]377
[36]378Private
[209]379 Sub initialize(ticks As Int64, kind As DateTimeKind)
380 Kind = kind
381 Ticks = ticks
382 End Sub
383
384 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)
385 If month < 1 Or month > 12 _
386 Or day < 1 Or day > DaysInMonth(year, month) _
387 Or hour < 0 Or hour => 24 _
388 Or minute < 0 Or minute => 60 _
389 Or second < 0 Or second => 60 _
390 Or millisecond < 0 Or millisecond => 1000 Then
391 debug 'ArgumentOutOfRangeException
392 End If
393
394 initialize(
[263]395 yearToDay(year) * TimeSpan.TicksPerDay _
396 + totalDaysOfMonth(year, month - 1) * TimeSpan.TicksPerDay _
[209]397 + (day - 1) * TimeSpan.TicksPerDay _
398 + hour * TimeSpan.TicksPerHour _
399 + minute * TimeSpan.TicksPerMinute _
400 + second * TimeSpan.TicksPerSecond _
401 + millisecond * TimeSpan.TicksPerMillisecond,
402 kind
403 )
404 End Sub
405
[36]406 Sub Ticks(value As Int64)
[209]407 If value < MinValue Or value > MaxValue Then
408 debug 'ArgumentOutOfRangeException
409 End If
410
411 Dim temp = Kind As DateTimeKind
[36]412 m_Date = value
[209]413 Kind = temp
[36]414 End Sub
415
416 Sub Kind(kind As DateTimeKind)
417 Dim temp As Int64
418 temp = kind
419 temp = (temp << 62) And &HC000000000000000
420 m_Date = (m_Date And &H3FFFFFFFFFFFFFFF) Or temp
421 End Sub
422
[209]423 Static Function kindFromBinary(date As Int64) As DateTimeKind
424 date = (date >> 62) And &H03
425 If date = &H01 Then
[103]426 Return DateTimeKind.Local
[209]427 ElseIf date = &H02 Then
[103]428 Return DateTimeKind.Unspecified
[209]429 ElseIf date = &H03 Then
[103]430 Return DateTimeKind.Utc
[36]431 End If
[246]432
433 ' ここにはこないはず
434 debug
[36]435 End Function
[209]436
437 Function getSystemTime() As SYSTEMTIME
438 Dim time As SYSTEMTIME
439 With time
440 .wYear = Year As Word
441 .wMonth = Month As Word
442 .wDayOfWeek = DayOfWeek As Word
443 .wDay = Day As Word
444 .wHour = Hour As Word
445 .wMinute = Minute As Word
446 .wSecond = Second As Word
447 .wMilliseconds = Millisecond As Word
448 End With
449 Return time
450 End Function
451
[263]452 Static Function yearToDay(year As Long) As Long
453 year--
[209]454 Return (Int(year * 365.25) - Int(year * 0.01) + Int(year * 0.0025))
455 End Function
456
[263]457 Static Function totalDaysOfMonth(year As Long, month As Long) As Long
[209]458 Dim days As Long
459 Dim i As Long
460 For i = 1 To month
461 days += DaysInMonth(year, i)
462 Next
463 Return days
464 End Function
[36]465End Class
466
[103]467Enum DateTimeKind
[36]468 Local
469 Unspecified
470 Utc
471End Enum
472
[103]473Enum DayOfWeek
[36]474 Sunday = 0
475 Monday
476 Tuesday
477 Wednesday
478 Thursday
479 Friday
480 Saturday
[209]481End Enum
Note: See TracBrowser for help on using the repository browser.