@@ -47,11 +47,86 @@ struct TzRule {
47
47
48
48
#[ derive( Debug ) ]
49
49
struct TzRuleDate {
50
- month : i8 ,
51
50
day : i8 ,
52
51
day_of_week : i8 ,
53
- seconds_of_day : i32 ,
54
- time_mode : i8 ,
52
+ month : u8 ,
53
+ millis_of_day : u32 ,
54
+ time_mode : TimeMode ,
55
+ mode : & ' static str ,
56
+ }
57
+
58
+ #[ derive( Debug ) ]
59
+ pub enum TimeMode {
60
+ Wall = 0 ,
61
+ Standard = 1 ,
62
+ Utc = 2 ,
63
+ }
64
+
65
+ impl TzRuleDate {
66
+ fn new (
67
+ mut day : i8 ,
68
+ mut day_of_week : i8 ,
69
+ month : u8 ,
70
+ millis_of_day : u32 ,
71
+ time_mode : i8 ,
72
+ ) -> Option < Self > {
73
+ const GREGORIAN_MONTHS : [ i8 ; 12 ] = [ 31 , 29 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ] ;
74
+
75
+ if day == 0 {
76
+ return None ;
77
+ }
78
+ if month > 11 {
79
+ return None ;
80
+ }
81
+ if millis_of_day > 24 * 60 * 60 * 1000 {
82
+ return None ;
83
+ }
84
+
85
+ let time_mode = match time_mode {
86
+ 0 => TimeMode :: Wall ,
87
+ 1 => TimeMode :: Standard ,
88
+ 2 => TimeMode :: Utc ,
89
+ _ => return None ,
90
+ } ;
91
+
92
+ let mode;
93
+
94
+ if day_of_week == 0 {
95
+ mode = "dom" ;
96
+ } else {
97
+ if day_of_week > 0 {
98
+ mode = "dow_in_month"
99
+ } else {
100
+ day_of_week = -day_of_week;
101
+ if day > 0 {
102
+ mode = "dow_ge_dom" ;
103
+ } else {
104
+ day = -day;
105
+ mode = "dow_le_dom" ;
106
+ }
107
+ }
108
+ if day_of_week > 7 {
109
+ return None ;
110
+ }
111
+ }
112
+
113
+ if mode == "dow_in_month" {
114
+ if !( -5 ..=5 ) . contains ( & day) {
115
+ return None ;
116
+ }
117
+ } else if day < 1 || day > GREGORIAN_MONTHS [ month as usize ] {
118
+ return None ;
119
+ }
120
+
121
+ Some ( Self {
122
+ day,
123
+ day_of_week,
124
+ month,
125
+ millis_of_day,
126
+ time_mode,
127
+ mode,
128
+ } )
129
+ }
55
130
}
56
131
57
132
impl < ' de > Deserialize < ' de > for ZoneInfo64 < ' de > {
@@ -191,20 +266,22 @@ impl<'de> Deserialize<'de> for ZoneInfo64<'de> {
191
266
key,
192
267
TzRule {
193
268
additional_offset_secs : value[ 10 ] ,
194
- start : TzRuleDate {
195
- month : value[ 0 ] as i8 ,
196
- day : value[ 1 ] as i8 ,
197
- day_of_week : value[ 2 ] as i8 ,
198
- seconds_of_day : value[ 3 ] ,
199
- time_mode : value[ 4 ] as i8 ,
200
- } ,
201
- end : TzRuleDate {
202
- month : value[ 5 ] as i8 ,
203
- day : value[ 6 ] as i8 ,
204
- day_of_week : value[ 7 ] as i8 ,
205
- seconds_of_day : value[ 8 ] ,
206
- time_mode : value[ 9 ] as i8 ,
207
- } ,
269
+ start : TzRuleDate :: new (
270
+ value[ 1 ] as i8 ,
271
+ value[ 2 ] as i8 ,
272
+ value[ 0 ] as u8 ,
273
+ value[ 3 ] as u32 ,
274
+ value[ 4 ] as i8 ,
275
+ )
276
+ . unwrap ( ) ,
277
+ end : TzRuleDate :: new (
278
+ value[ 6 ] as i8 ,
279
+ value[ 7 ] as i8 ,
280
+ value[ 5 ] as u8 ,
281
+ value[ 8 ] as u32 ,
282
+ value[ 9 ] as i8 ,
283
+ )
284
+ . unwrap ( ) ,
208
285
} ,
209
286
) ) ;
210
287
}
@@ -445,14 +522,16 @@ impl Rule<'_> {
445
522
let _ = self . inner . start . month ;
446
523
let _ = self . inner . start . day ;
447
524
let _ = self . inner . start . day_of_week ;
448
- let _ = self . inner . start . seconds_of_day ;
525
+ let _ = self . inner . start . millis_of_day ;
449
526
let _ = self . inner . start . time_mode ;
527
+ let _ = self . inner . start . mode ;
450
528
451
529
let _ = self . inner . end . month ;
452
530
let _ = self . inner . end . day ;
453
531
let _ = self . inner . end . day_of_week ;
454
- let _ = self . inner . end . seconds_of_day ;
532
+ let _ = self . inner . end . millis_of_day ;
455
533
let _ = self . inner . end . time_mode ;
534
+ let _ = self . inner . end . mode ;
456
535
457
536
Transition {
458
537
transition,
0 commit comments