1
- import {
2
- UTC as Date_UTC ,
3
- now as Date_now
4
- } from "./bindings/Date" ;
1
+ import { E_VALUEOUTOFRANGE } from "util/error" ;
2
+ import { UTC as Date_UTC , now as Date_now } from "./bindings/Date" ;
5
3
6
4
export class Date {
7
-
8
5
@inline static UTC (
9
6
year : i32 ,
10
7
month : i32 = 0 ,
@@ -14,25 +11,157 @@ export class Date {
14
11
second : i32 = 0 ,
15
12
millisecond : i64 = 0
16
13
) : i64 {
17
- return < i64 > Date_UTC ( year , month , day , hour , minute , second , < f64 > millisecond ) ;
14
+ return < i64 > (
15
+ Date_UTC ( year , month , day , hour , minute , second , < f64 > millisecond )
16
+ ) ;
18
17
}
19
18
20
19
@inline static now ( ) : i64 {
21
20
return < i64 > Date_now ( ) ;
22
21
}
23
22
24
- private value : i64 ;
23
+ private epochMillis : i64 ;
25
24
26
- constructor ( value : i64 ) {
27
- this . value = value ;
25
+ constructor ( epochMillis : i64 ) {
26
+ this . epochMillis = epochMillis ;
28
27
}
29
28
30
29
getTime ( ) : i64 {
31
- return this . value ;
30
+ return this . epochMillis ;
32
31
}
33
32
34
33
setTime ( value : i64 ) : i64 {
35
- this . value = value ;
34
+ this . epochMillis = value ;
36
35
return value ;
37
36
}
37
+
38
+ getUTCFullYear ( ) : i32 {
39
+ return ymdFromEpochDays ( i32 ( this . epochMillis / MILLIS_PER_DAY ) ) . year ;
40
+ }
41
+
42
+ getUTCMonth ( ) : i32 {
43
+ return ymdFromEpochDays ( i32 ( this . epochMillis / MILLIS_PER_DAY ) ) . month - 1 ;
44
+ }
45
+
46
+ getUTCDate ( ) : i32 {
47
+ return ymdFromEpochDays ( i32 ( this . epochMillis / MILLIS_PER_DAY ) ) . day ;
48
+ }
49
+
50
+ getUTCHours ( ) : i32 {
51
+ return i32 ( this . epochMillis % MILLIS_PER_DAY ) / MILLIS_PER_HOUR ;
52
+ }
53
+
54
+ getUTCMinutes ( ) : i32 {
55
+ return i32 ( this . epochMillis % MILLIS_PER_HOUR ) / MILLIS_PER_MINUTE ;
56
+ }
57
+
58
+ getUTCSeconds ( ) : i32 {
59
+ return i32 ( this . epochMillis % MILLIS_PER_MINUTE ) / MILLIS_PER_SECOND ;
60
+ }
61
+
62
+ getUTCMilliseconds ( ) : i32 {
63
+ return i32 ( this . epochMillis % MILLIS_PER_SECOND ) ;
64
+ }
65
+
66
+ setUTCMilliseconds ( value : i32 ) : void {
67
+ this . epochMillis += value - this . getUTCMilliseconds ( ) ;
68
+ }
69
+
70
+ setUTCSeconds ( value : i32 ) : void {
71
+ throwIfNotInRange ( value , 0 , 59 ) ;
72
+ this . epochMillis += ( value - this . getUTCSeconds ( ) ) * MILLIS_PER_SECOND ;
73
+ }
74
+
75
+ setUTCMinutes ( value : i32 ) : void {
76
+ throwIfNotInRange ( value , 0 , 59 ) ;
77
+ this . epochMillis += ( value - this . getUTCMinutes ( ) ) * MILLIS_PER_MINUTE ;
78
+ }
79
+
80
+ setUTCHours ( value : i32 ) : void {
81
+ throwIfNotInRange ( value , 0 , 23 ) ;
82
+ this . epochMillis += ( value - this . getUTCHours ( ) ) * MILLIS_PER_HOUR ;
83
+ }
84
+
85
+ setUTCDate ( value : i32 ) : void {
86
+ const ymd = ymdFromEpochDays ( i32 ( this . epochMillis / MILLIS_PER_DAY ) ) ;
87
+ throwIfNotInRange ( value , 1 , lastDayOfMonth ( ymd . year , ymd . month ) ) ;
88
+ const mills = this . epochMillis % MILLIS_PER_DAY ;
89
+ this . epochMillis =
90
+ i64 ( daysSinceEpoch ( ymd . year , ymd . month , value ) ) * MILLIS_PER_DAY + mills ;
91
+ }
92
+
93
+ setUTCMonth ( value : i32 ) : void {
94
+ throwIfNotInRange ( value , 1 , 12 ) ;
95
+ const ymd = ymdFromEpochDays ( i32 ( this . epochMillis / MILLIS_PER_DAY ) ) ;
96
+ const mills = this . epochMillis % MILLIS_PER_DAY ;
97
+ this . epochMillis =
98
+ i64 ( daysSinceEpoch ( ymd . year , value + 1 , ymd . day ) ) * MILLIS_PER_DAY +
99
+ mills ;
100
+ }
101
+
102
+ setUTCFullYear ( value : i32 ) : void {
103
+ const ymd = ymdFromEpochDays ( i32 ( this . epochMillis / MILLIS_PER_DAY ) ) ;
104
+ const mills = this . epochMillis % MILLIS_PER_DAY ;
105
+ this . epochMillis =
106
+ i64 ( daysSinceEpoch ( value , ymd . month , ymd . day ) ) * MILLIS_PER_DAY + mills ;
107
+ }
108
+ }
109
+
110
+ function throwIfNotInRange ( value : i32 , lower : i32 , upper : i32 ) : void {
111
+ if ( value < lower || value > upper ) throw new RangeError ( E_VALUEOUTOFRANGE ) ;
112
+ }
113
+
114
+ const MILLIS_PER_DAY = 1_000 * 60 * 60 * 24 ;
115
+ const MILLIS_PER_HOUR = 1_000 * 60 * 60 ;
116
+ const MILLIS_PER_MINUTE = 1_000 * 60 ;
117
+ const MILLIS_PER_SECOND = 1_000 ;
118
+
119
+ class YMD {
120
+ year : i32 ;
121
+ month : i32 ;
122
+ day : i32 ;
123
+ }
124
+
125
+ // http://howardhinnant.github.io/date_algorithms.html#is_leap
126
+ function isLeap ( y : i32 ) : bool {
127
+ return y % 4 == 0 && ( y % 100 != 0 || y % 400 == 0 ) ;
128
+ }
129
+
130
+ // http://howardhinnant.github.io/date_algorithms.html#last_day_of_month_common_year
131
+ function lastDayOfMonthNonLeapYear ( m : i32 ) : i32 {
132
+ const days = [ 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ] ;
133
+ return days [ m - 1 ] ;
134
+ }
135
+
136
+ // http://howardhinnant.github.io/date_algorithms.html#last_day_of_month
137
+ function lastDayOfMonth ( y : i32 , m : i32 ) : i32 {
138
+ return m != 2 || ! isLeap ( y ) ? lastDayOfMonthNonLeapYear ( m ) : 29 ;
139
+ }
140
+
141
+ // see: http://howardhinnant.github.io/date_algorithms.html#civil_from_days
142
+ function ymdFromEpochDays ( z : i32 ) : YMD {
143
+ z += 719468 ;
144
+ const era = ( z >= 0 ? z : z - 146096 ) / 146097 ;
145
+ const doe = z - era * 146097 ; // [0, 146096]
146
+ const yoe = ( doe - doe / 1460 + doe / 36524 - doe / 146096 ) / 365 ; // [0, 399]
147
+ const y = yoe + era * 400 ;
148
+ const doy = doe - ( 365 * yoe + yoe / 4 - yoe / 100 ) ; // [0, 365]
149
+ const mp = ( 5 * doy + 2 ) / 153 ; // [0, 11]
150
+ const d = doy - ( 153 * mp + 2 ) / 5 + 1 ; // [1, 31]
151
+ const m = mp + ( mp < 10 ? 3 : - 9 ) ; // [1, 12]
152
+ return {
153
+ year : y + ( m <= 2 ? 1 : 0 ) ,
154
+ month : m ,
155
+ day : d ,
156
+ } ;
157
+ }
158
+
159
+ // http://howardhinnant.github.io/date_algorithms.html#days_from_civil
160
+ function daysSinceEpoch ( y : i32 , m : i32 , d : i32 ) : i32 {
161
+ y -= m <= 2 ? 1 : 0 ;
162
+ const era = ( y >= 0 ? y : y - 399 ) / 400 ;
163
+ const yoe = y - era * 400 ; // [0, 399]
164
+ const doy = ( 153 * ( m + ( m > 2 ? - 3 : 9 ) ) + 2 ) / 5 + d - 1 ; // [0, 365]
165
+ const doe = yoe * 365 + yoe / 4 - yoe / 100 + doy ; // [0, 146096]
166
+ return era * 146097 + doe - 719468 ;
38
167
}
0 commit comments