Skip to content

Commit dafdb58

Browse files
fix: do not add TZID for utc datetime (#464)
1 parent c3547cc commit dafdb58

File tree

4 files changed

+33
-5
lines changed

4 files changed

+33
-5
lines changed

lib/rrule/dtstart.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ impl DtStart {
3434
let mut parameters = Parameters::new();
3535

3636
if let Some(tzid) = self.tzid {
37-
parameters.insert("TZID".to_string(), tzid.to_string());
37+
// UTC datetimes MUST NOT contain a TZID
38+
if !self.datetime.utc() {
39+
parameters.insert("TZID".to_string(), tzid.to_string());
40+
}
3841
}
3942

4043
let value: String = self.datetime.to_string();

lib/rrule/exdate.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ impl ExDate {
2626
let mut parameters = Parameters::new();
2727

2828
if let Some(tzid) = self.tzid {
29-
parameters.insert("TZID".to_string(), tzid.to_string());
29+
// UTC datetimes MUST NOT contain a TZID
30+
if !self.datetimes.iter().any(|datetime| datetime.utc()) {
31+
parameters.insert("TZID".to_string(), tzid.to_string());
32+
}
3033
}
3134

3235
let value: String = self

lib/rrule/rdate.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ impl RDate {
2626
let mut parameters = Parameters::new();
2727

2828
if let Some(tzid) = self.tzid {
29-
parameters.insert("TZID".to_string(), tzid.to_string());
29+
// UTC datetimes MUST NOT contain a TZID
30+
if !self.datetimes.iter().any(|datetime| datetime.utc()) {
31+
parameters.insert("TZID".to_string(), tzid.to_string());
32+
}
3033
}
3134

3235
let value: String = self

tests/serialization/rrule_set.spec.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { RRuleSet, DateTime } from '../../src';
1+
import { RRuleSet, DateTime, RRule } from '../../src';
22

33
describe(RRuleSet, () => {
44
it('should properly parse weekly recurrence', () => {
@@ -210,7 +210,7 @@ describe(RRuleSet, () => {
210210
},
211211
},
212212
])(
213-
'should parse rdate property when dtstart is $dtstart and rdate is $exdate',
213+
'should parse rdate property when dtstart is $dtstart and rdate is $rdate',
214214
({ dtstart, rdate, expected }) => {
215215
const set = RRuleSet.parse(
216216
`${dtstart}\n${rdate}\nRRULE:FREQ=WEEKLY;UNTIL=20190208T045959Z;INTERVAL=2;BYDAY=FR`,
@@ -221,4 +221,23 @@ describe(RRuleSet, () => {
221221
expect(set.toString()).toContain(rdate);
222222
},
223223
);
224+
225+
// see https://icalendar.org/iCalendar-RFC-5545/3-2-19-time-zone-identifier.html
226+
it('should not add TZID=UTC to dates if they are in UTC', () => {
227+
const utcDate = DateTime.fromObject(
228+
{ year: 2025, month: 1, day: 1, hour: 0, minute: 0, second: 0 },
229+
{ utc: true },
230+
);
231+
232+
const set = new RRuleSet({
233+
dtstart: utcDate,
234+
rrules: [new RRule(1)],
235+
exdates: [utcDate],
236+
rdates: [utcDate],
237+
});
238+
239+
expect(set.toString()).toBe(
240+
'DTSTART:20250101T000000Z\nRRULE:FREQ=MONTHLY\nEXDATE:20250101T000000Z\nRDATE:20250101T000000Z',
241+
);
242+
});
224243
});

0 commit comments

Comments
 (0)