iamcal 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +47 -11
  2. package/lib/component.d.ts +46 -9
  3. package/lib/component.d.ts.map +1 -1
  4. package/lib/component.js +105 -17
  5. package/lib/components/Calendar.d.ts +35 -14
  6. package/lib/components/Calendar.d.ts.map +1 -1
  7. package/lib/components/Calendar.js +43 -15
  8. package/lib/components/CalendarEvent.d.ts +84 -22
  9. package/lib/components/CalendarEvent.d.ts.map +1 -1
  10. package/lib/components/CalendarEvent.js +142 -67
  11. package/lib/components/TimeZone.d.ts +62 -39
  12. package/lib/components/TimeZone.d.ts.map +1 -1
  13. package/lib/components/TimeZone.js +81 -86
  14. package/lib/components/TimeZoneOffset.d.ts +103 -0
  15. package/lib/components/TimeZoneOffset.d.ts.map +1 -0
  16. package/lib/components/TimeZoneOffset.js +148 -0
  17. package/lib/components/index.d.ts +1 -0
  18. package/lib/components/index.d.ts.map +1 -1
  19. package/lib/components/index.js +2 -1
  20. package/lib/date.d.ts +165 -0
  21. package/lib/date.d.ts.map +1 -0
  22. package/lib/date.js +373 -0
  23. package/lib/index.d.ts +3 -1
  24. package/lib/index.d.ts.map +1 -1
  25. package/lib/index.js +4 -2
  26. package/lib/io.d.ts +9 -7
  27. package/lib/io.d.ts.map +1 -1
  28. package/lib/io.js +16 -11
  29. package/lib/parse.d.ts +32 -15
  30. package/lib/parse.d.ts.map +1 -1
  31. package/lib/parse.js +55 -53
  32. package/lib/patterns.d.ts +36 -0
  33. package/lib/patterns.d.ts.map +1 -0
  34. package/lib/patterns.js +50 -0
  35. package/lib/property.d.ts +149 -0
  36. package/lib/property.d.ts.map +1 -0
  37. package/lib/property.js +450 -0
  38. package/package.json +50 -38
  39. package/src/component.ts +132 -23
  40. package/src/components/Calendar.ts +58 -20
  41. package/src/components/CalendarEvent.ts +170 -66
  42. package/src/components/TimeZone.ts +86 -96
  43. package/src/components/TimeZoneOffset.ts +187 -0
  44. package/src/components/index.ts +2 -1
  45. package/src/date.ts +395 -0
  46. package/src/index.ts +3 -1
  47. package/src/io.ts +16 -11
  48. package/src/parse.ts +71 -51
  49. package/src/patterns.ts +69 -0
  50. package/src/property.ts +492 -0
@@ -1,43 +1,81 @@
1
- import { Component } from "../component"
2
- import { parseDate, toDateString, toDateTimeString } from "../parse"
1
+ import { KnownPropertyName, PropertyValidationError } from '../property'
2
+ import { ComponentValidationError, Component } from '../component'
3
+ import {
4
+ CalendarDateTime,
5
+ convertDate,
6
+ CalendarDateOrTime,
7
+ parseDateProperty,
8
+ toDateTimeString,
9
+ } from '../date'
3
10
 
4
11
  /**
5
12
  * Represents a VEVENT component, representing an event in a calendar.
6
13
  */
7
14
  export class CalendarEvent extends Component {
8
- name = 'VEVENT';
15
+ name = 'VEVENT'
9
16
 
10
- constructor(uid: string, dtstamp: Date)
17
+ constructor(
18
+ uid: string,
19
+ dtstamp: CalendarDateTime | Date,
20
+ dtstart: CalendarDateOrTime | Date
21
+ )
11
22
  constructor(component: Component)
12
- constructor(a: string | Component, b?: Date) {
13
- var component: Component
14
- if (b) {
23
+ constructor(
24
+ a: string | Component,
25
+ b?: CalendarDateTime | Date,
26
+ c?: CalendarDateOrTime | Date
27
+ ) {
28
+ let component: Component
29
+ if (a instanceof Component) {
30
+ component = a as Component
31
+ CalendarEvent.prototype.validate.call(component)
32
+ } else {
15
33
  const uid = a as string
16
- const dtstamp = b as Date
34
+ const dtstamp = convertDate(b!, false)
35
+ const dtstart = convertDate(c!)
17
36
  component = new Component('VEVENT')
18
37
  component.setProperty('UID', uid)
19
- component.setProperty('DTSTAMP', toDateTimeString(dtstamp))
20
- } else {
21
- component = a as Component
38
+ component.setProperty('DTSTAMP', dtstamp)
39
+ component.setProperty('DTSTART', dtstart)
22
40
  }
23
41
  super(component.name, component.properties, component.components)
24
42
  }
25
43
 
26
- stamp(): Date {
27
- return parseDate(this.getProperty('DTSTAMP')!)
44
+ serialize(): string {
45
+ if (!this.getEnd() && !this.duration()) {
46
+ throw new Error(
47
+ 'Failed to serialize calendar event, end or duration must be set'
48
+ )
49
+ }
50
+ return super.serialize()
28
51
  }
29
52
 
30
- setStamp(value: Date, fullDay: boolean = false): this {
31
- if (fullDay) {
32
- this.setProperty('DTSTAMP', toDateString(value))
33
- this.setPropertyParams('DTSTAMP', ['VALUE=DATE'])
34
- } else {
35
- this.setProperty('DTSTAMP', toDateTimeString(value))
53
+ validate() {
54
+ if (this.name !== 'VEVENT')
55
+ throw new ComponentValidationError('Component name must be VEVENT')
56
+ const requiredProperties: KnownPropertyName[] = [
57
+ 'UID',
58
+ 'DTSTAMP',
59
+ 'DTSTART',
60
+ ]
61
+ this.validateAllProperties(requiredProperties)
62
+ }
63
+
64
+ getStamp(): CalendarDateTime {
65
+ return parseDateProperty(
66
+ this.getProperty('DTSTAMP')!
67
+ ) as CalendarDateTime
68
+ }
69
+
70
+ setStamp(value: CalendarDateTime | Date): this {
71
+ const converted = convertDate(value, false)
72
+ if (converted.isFullDay()) {
73
+ throw new PropertyValidationError('DTSTAMP cannot be of type DATE')
36
74
  }
37
- return this
75
+ return this.setProperty('DTSTAMP', converted)
38
76
  }
39
77
 
40
- uid(): string {
78
+ getUid(): string {
41
79
  return this.getProperty('UID')!.value
42
80
  }
43
81
 
@@ -45,8 +83,8 @@ export class CalendarEvent extends Component {
45
83
  return this.setProperty('UID', value)
46
84
  }
47
85
 
48
- summary(): string {
49
- return this.getProperty('SUMMARY')!.value
86
+ getSummary(): string | undefined {
87
+ return this.getProperty('SUMMARY')?.value
50
88
  }
51
89
 
52
90
  setSummary(value: string): this {
@@ -57,8 +95,8 @@ export class CalendarEvent extends Component {
57
95
  this.removePropertiesWithName('SUMMARY')
58
96
  }
59
97
 
60
- description(): string {
61
- return this.getProperty('DESCRIPTION')!.value
98
+ getDescription(): string | undefined {
99
+ return this.getProperty('DESCRIPTION')?.value
62
100
  }
63
101
 
64
102
  setDescription(value: string): this {
@@ -69,7 +107,7 @@ export class CalendarEvent extends Component {
69
107
  this.removePropertiesWithName('DESCRIPTION')
70
108
  }
71
109
 
72
- location(): string | undefined {
110
+ getLocation(): string | undefined {
73
111
  return this.getProperty('LOCATION')?.value
74
112
  }
75
113
 
@@ -82,57 +120,98 @@ export class CalendarEvent extends Component {
82
120
  }
83
121
 
84
122
  /**
85
- * Get the start of the event.
86
- * If set as a full day the time will be at the start of the day.
123
+ * Get the start date or time of the event.
124
+ * @returns The start date or time of the event as a {@link CalendarDateOrTime}.
87
125
  */
88
- start(): Date {
89
- return parseDate(this.getProperty('DTSTART')!)
90
- }
91
-
92
- /** Set the start of the event. */
93
- setStart(value: Date, fullDay: boolean = false): this {
94
- if (fullDay) {
95
- this.setProperty('DTSTART', toDateString(value))
96
- this.setPropertyParams('DTSTART', ['VALUE=DATE'])
97
- } else {
98
- this.setProperty('DTSTART', toDateTimeString(value))
99
- }
100
- return this
126
+ getStart(): CalendarDateOrTime {
127
+ return parseDateProperty(this.getProperty('DTSTART')!)
101
128
  }
102
129
 
103
- removeStart() {
104
- this.removePropertiesWithName('DTSTART')
130
+ /**
131
+ * Set the start date or time of the event.
132
+ * @param value The start date of the event as a {@link CalendarDateOrTime} or `Date`.
133
+ * @returns The CalendarEvent instance for chaining.
134
+ */
135
+ setStart(value: CalendarDateOrTime | Date): this {
136
+ return this.setProperty('DTSTART', convertDate(value))
105
137
  }
106
138
 
107
139
  /**
108
140
  * Get the non-inclusive end of the event.
109
- * If set as a full day the time will be at the start of the day.
141
+ * @returns The end date of the event as a {@link CalendarDateOrTime} or `undefined` if not set.
110
142
  */
111
- end(): Date {
112
- return parseDate(this.getProperty('DTEND')!)
143
+ getEnd(): CalendarDateOrTime | undefined {
144
+ const property = this.getProperty('DTEND')
145
+ if (!property) return
146
+ return parseDateProperty(property)
113
147
  }
114
148
 
115
149
  /**
116
- * Set the non-inclusive end of the event.
150
+ * Set the exclusive end of the event.
151
+ *
152
+ * Will remove 'duration' if present.
153
+ * @param value The end date of the event as a {@link CalendarDateOrTime} or `Date`.
154
+ * @returns The CalendarEvent instance for chaining.
155
+ * @throws If the end date is a full day date and the start date is a date-time, or vice versa.
117
156
  */
118
- setEnd(value: Date, fullDay: boolean = false): this {
119
- if (fullDay) {
120
- this.setProperty('DTEND', toDateString(value))
121
- this.setPropertyParams('DTEND', ['VALUE=DATE'])
122
- } else {
123
- this.setProperty('DTEND', toDateTimeString(value))
157
+ setEnd(value: CalendarDateOrTime | Date): this {
158
+ const date = convertDate(value)
159
+ const start = this.getStart()
160
+ if (date.isFullDay() !== start.isFullDay()) {
161
+ throw new Error(
162
+ `End must be same date type as start. Start is ${start.isFullDay() ? 'date' : 'datetime'} but new end value is ${date.isFullDay() ? 'date' : 'datetime'}`
163
+ )
124
164
  }
125
- return this
165
+
166
+ this.removeDuration()
167
+ return this.setProperty('DTEND', date)
126
168
  }
127
169
 
170
+ /**
171
+ * Remove the end of the event.
172
+ *
173
+ * NOTE: An event must have either an end or a duration set.
174
+ */
128
175
  removeEnd() {
129
176
  this.removePropertiesWithName('DTEND')
130
177
  }
131
178
 
132
- created(): Date | undefined {
179
+ /**
180
+ * Get the duration of the event as a string formatted according to the iCalendar specification.
181
+ * @returns The duration of the event, or `undefined` if not set.
182
+ */
183
+ getDuration(): string | undefined {
184
+ return this.getProperty('DURATION')?.value
185
+ }
186
+
187
+ /**
188
+ * Set the duration of the event.
189
+ *
190
+ * Will remove 'end' if present.
191
+ * @param value The duration of the event as a string in the format defined by RFC5545.
192
+ * @returns The CalendarEvent instance for chaining.
193
+ * @example
194
+ * // Set duration to 1 hour and 30 minutes.
195
+ * event.setDuration(`PT1H30M`)
196
+ */
197
+ setDuration(value: string): this {
198
+ this.removeEnd()
199
+ return this.setProperty('DURATION', value)
200
+ }
201
+
202
+ /**
203
+ * Remove the duration of the event.
204
+ *
205
+ * NOTE: An event must have either an end or a duration set.
206
+ */
207
+ removeDuration() {
208
+ this.removePropertiesWithName('DURATION')
209
+ }
210
+
211
+ getCreated(): CalendarDateOrTime | undefined {
133
212
  const property = this.getProperty('CREATED')
134
213
  if (!property) return
135
- return parseDate(property)
214
+ return parseDateProperty(property)
136
215
  }
137
216
 
138
217
  setCreated(value: Date): this {
@@ -143,24 +222,49 @@ export class CalendarEvent extends Component {
143
222
  this.removePropertiesWithName('CREATED')
144
223
  }
145
224
 
146
- geo(): [number, number] | undefined {
225
+ getGeographicPosition(): [number, number] | undefined {
147
226
  const text = this.getProperty('GEO')?.value
148
227
  if (!text) return
149
- const pattern = /^[+-]?\d+(\.\d+)?,[+-]?\d+(\.\d+)?$/
150
- if (!pattern.test(text)) throw new Error(`Failed to parse GEO property: ${text}`)
228
+ const validGeoPattern = /^[+-]?\d+(\.\d+)?;[+-]?\d+(\.\d+)?$/
229
+ if (!validGeoPattern.test(text))
230
+ throw new Error(`Failed to parse GEO property: ${text}`)
151
231
  const [longitude, latitude] = text.split(',')
152
232
  return [parseFloat(longitude), parseFloat(latitude)]
153
233
  }
154
234
 
155
- setGeo(latitude: number, longitude: number): this {
156
- const text = `${latitude},${longitude}`
157
- return this
235
+ setGeographicPosition(latitude: number, longitude: number): this {
236
+ const text = `${latitude};${longitude}`
237
+ return this.setProperty('GEO', text)
158
238
  }
159
239
 
160
- removeGeo() {
240
+ removeGeographicLocation() {
161
241
  this.removePropertiesWithName('GEO')
162
242
  }
163
- }
164
243
 
165
- const event = new CalendarEvent('abc', new Date())
166
- event.getPropertyParams('DTEND')?.includes('VALUE=DATE')
244
+ /* eslint-disable */
245
+
246
+ /** @deprecated use {@link getStamp} instead */
247
+ stamp = this.getStamp
248
+ /** @deprecated use {@link getUid} instead */
249
+ uid = this.getUid
250
+ /** @deprecated use {@link getSummary} instead */
251
+ summary = this.getSummary
252
+ /** @deprecated use {@link getDescription} instead */
253
+ description = this.getDescription
254
+ /** @deprecated use {@link getLocation} instead */
255
+ location = this.getLocation
256
+ /** @deprecated use {@link getStart} instead */
257
+ start = this.getStart
258
+ /** @deprecated use {@link getEnd} instead */
259
+ end = this.getEnd
260
+ /** @deprecated use {@link getDuration} instead */
261
+ duration = this.getDuration
262
+ /** @deprecated use {@link getCreated} instead */
263
+ created = this.getCreated
264
+ /** @deprecated use {@link getGeographicPosition} instead */
265
+ geo = this.getGeographicPosition
266
+ /** @deprecated use {@link setGeographicPosition} instead */
267
+ setGeo = this.setGeographicPosition
268
+ /** @deprecated use {@link removeGeographicLocation} instead */
269
+ removeGeo = this.removeGeographicLocation
270
+ }
@@ -1,16 +1,21 @@
1
- import { Component } from '../component'
2
- import { parseDate, toDateString, toDateTimeString } from '../parse'
1
+ import { Component, ComponentValidationError } from '../component'
2
+ import { CalendarDateOrTime, parseDateProperty } from '../date'
3
+ import { KnownPropertyName } from '../property'
4
+ import { TimeZoneOffset } from './TimeZoneOffset'
3
5
 
4
6
  /**
5
7
  * Represents a VTIMEZONE component, containing time zone definitions.
6
8
  */
7
9
  export class TimeZone extends Component {
10
+ name = 'VTIMEZONE'
11
+
8
12
  constructor(id: string)
9
13
  constructor(component: Component)
10
14
  constructor(a: string | Component) {
11
- var component: Component
15
+ let component: Component
12
16
  if (a instanceof Component) {
13
17
  component = a as Component
18
+ TimeZone.prototype.validate.call(component)
14
19
  } else {
15
20
  const tzid = a as string
16
21
  component = new Component('VTIMEZONE')
@@ -19,7 +24,14 @@ export class TimeZone extends Component {
19
24
  super(component.name, component.properties, component.components)
20
25
  }
21
26
 
22
- id(): string {
27
+ validate() {
28
+ if (this.name !== 'VTIMEZONE')
29
+ throw new ComponentValidationError('Component name must be VEVENT')
30
+ const requiredProperties: KnownPropertyName[] = ['TZID']
31
+ this.validateAllProperties(requiredProperties)
32
+ }
33
+
34
+ getId(): string {
23
35
  return this.getProperty('TZID')!.value
24
36
  }
25
37
 
@@ -27,21 +39,21 @@ export class TimeZone extends Component {
27
39
  return this.setProperty('TZID', value)
28
40
  }
29
41
 
30
- lastMod(): Date | undefined {
31
- const text = this.getProperty('LAST-MOD')
42
+ getLastModified(): CalendarDateOrTime | undefined {
43
+ const text = this.getProperty('LAST-MODIFIED')
32
44
  if (!text) return
33
- return parseDate(text)
45
+ return parseDateProperty(text)
34
46
  }
35
47
 
36
- setLastMod(value: Date): this {
37
- return this.setProperty('LAST-MOD', value.toISOString())
48
+ setLastModified(value: Date): this {
49
+ return this.setProperty('LAST-MODIFIED', value.toISOString())
38
50
  }
39
51
 
40
- removeLastMod() {
52
+ removeLastModified() {
41
53
  this.removePropertiesWithName('LAST-MOD')
42
54
  }
43
55
 
44
- url(): string | undefined {
56
+ getUrl(): string | undefined {
45
57
  return this.getProperty('TZURL')?.value
46
58
  }
47
59
 
@@ -53,110 +65,88 @@ export class TimeZone extends Component {
53
65
  this.removePropertiesWithName('TZURL')
54
66
  }
55
67
 
56
- /** Get all time offsets. */
57
- offsets(): TimeZoneOffset[] {
68
+ /**
69
+ * Get all time offsets.
70
+ * @returns An array of time zone offsets defined in this time zone.
71
+ */
72
+ getOffsets(): TimeZoneOffset[] {
58
73
  const offsets: TimeZoneOffset[] = []
59
74
  this.components.forEach(component => {
60
- if (component.name === 'STANDARD' || component.name === 'DAYLIGHT') {
75
+ if (
76
+ component.name === 'STANDARD' ||
77
+ component.name === 'DAYLIGHT'
78
+ ) {
61
79
  offsets.push(new TimeZoneOffset(component))
62
80
  }
63
81
  })
64
82
  return offsets
65
83
  }
66
84
 
67
- /** Get standard/winter time offsets. */
68
- standardOffsets(): TimeZoneOffset[] {
69
- return this.getComponents('STANDARD').map(c => new TimeZoneOffset(c))
70
- }
71
-
72
- /** Get daylight savings time offsets. */
73
- daylightOffsets(): TimeZoneOffset[] {
74
- return this.getComponents('DAYLIGHT').map(c => new TimeZoneOffset(c))
75
- }
76
- }
77
-
78
- export type OffsetType = 'DAYLIGHT' | 'STANDARD'
79
- type Digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
80
- export type Offset = `${'-' | '+'}${Digit}${Digit}${Digit}${Digit}`
81
- /** Represents a STANDARD or DAYLIGHT component, defining a time zone offset. */
82
- class TimeZoneOffset extends Component {
83
85
  /**
84
- *
85
- * @param type If this is a STANDARD or DAYLIGHT component.
86
- * @param start From when this offset is active.
87
- * @param offsetFrom The offset that is in use prior to this time zone observance.
88
- * @param offsetTo The offset that is in use during this time zone observance.
86
+ * Get standard/winter time offsets.
87
+ * @returns An array of time zone offsets defined in this time zone that are of type STANDARD.
89
88
  */
90
- constructor(type: OffsetType, start: Date, offsetFrom: Offset, offsetTo: Offset)
91
- constructor(component: Component)
92
- constructor(a: OffsetType | Component, b?: Date, c?: Offset, d?: Offset) {
93
- var component: Component
94
- if (a instanceof Component) {
95
- component = a as Component
96
- } else {
97
- const name = a as OffsetType
98
- const start = b as Date
99
- const offsetFrom = c as Offset
100
- const offsetTo = d as Offset
101
- component = new Component(name)
102
- component.setProperty('DTSTART', toDateTimeString(start))
103
- component.setProperty('TZOFFSETFROM', offsetFrom)
104
- component.setProperty('TZOFFSETTO', offsetTo)
105
- }
106
- super(component.name, component.properties, component.components)
107
- }
108
-
109
- start(): Date {
110
- return parseDate(this.getProperty('DTSTART')!)
111
- }
112
-
113
- setStart(value: Date, fullDay: boolean = false): this {
114
- if (fullDay) {
115
- this.setProperty('DTSTART', toDateString(value))
116
- this.setPropertyParams('DTSTART', ['VALUE=DATE'])
117
- } else {
118
- this.setProperty('DTSTART', toDateTimeString(value))
119
- }
120
- return this
89
+ getStandardOffsets(): TimeZoneOffset[] {
90
+ return this.getComponentsWithName('STANDARD').map(
91
+ c => new TimeZoneOffset(c)
92
+ )
121
93
  }
122
94
 
123
- offsetFrom(): Offset {
124
- return this.getProperty('TZOFFSETFROM')!.value as Offset
95
+ /**
96
+ * Get daylight savings time offsets.
97
+ * @returns An array of time zone offsets defined in this time zone that are of type DAYLIGHT.
98
+ */
99
+ getDaylightOffsets(): TimeZoneOffset[] {
100
+ return this.getComponentsWithName('DAYLIGHT').map(
101
+ c => new TimeZoneOffset(c)
102
+ )
125
103
  }
126
104
 
127
- setOffsetFrom(value: Offset): this {
128
- return this.setProperty('TZOFFSETFROM', value)
129
- }
105
+ /* eslint-disable */
130
106
 
131
- offsetTo(): Offset {
132
- return this.getProperty('TZOFFSETTO')!.value as Offset
133
- }
107
+ /**
108
+ * @deprecated Use {@link getId} instead.
109
+ */
110
+ id = this.getId
134
111
 
135
- setOffsetTo(value: Offset): this {
136
- return this.setProperty('TZOFFSETTO', value)
137
- }
112
+ /**
113
+ * @deprecated Use {@link getLastModified} instead.
114
+ */
115
+ lastMod = this.getLastModified
138
116
 
139
- comment(): string | undefined {
140
- return this.getProperty('COMMENT')?.value
141
- }
117
+ /**
118
+ * @deprecated Use {@link setLastModified} instead.
119
+ */
120
+ setLastMod = this.setLastModified
142
121
 
143
- setComment(value: string): this {
144
- return this.setProperty('COMMENT', value)
145
- }
122
+ /**
123
+ * @deprecated Use {@link removeLastModified} instead.
124
+ */
125
+ removeLastMod = this.removeLastModified
146
126
 
147
- removeComment() {
148
- this.removePropertiesWithName('COMMENT')
149
- }
127
+ /**
128
+ * @deprecated Use {@link getUrl} instead.
129
+ */
130
+ url = this.getUrl
150
131
 
151
- timeZoneName(): string | undefined {
152
- return this.getProperty('TZNAME')?.value
153
- }
132
+ /**
133
+ * Get all time offsets.
134
+ * @returns An array of time zone offsets defined in this time zone.
135
+ * @deprecated Use {@link getOffsets} instead.
136
+ */
137
+ offsets = this.getOffsets
154
138
 
155
- setTimeZoneName(value: string): this {
156
- return this.setProperty('TZNAME', value)
157
- }
139
+ /**
140
+ * Get standard/winter time offsets.
141
+ * @returns An array of time zone offsets defined in this time zone that are of type STANDARD.
142
+ * @deprecated Use {@link getStandardOffsets} instead.
143
+ */
144
+ standardOffsets = this.getStandardOffsets
158
145
 
159
- removeTimeZoneName() {
160
- this.removePropertiesWithName('TZNAME')
161
- }
162
- }
146
+ /**
147
+ * Get daylight savings time offsets.
148
+ * @returns An array of time zone offsets defined in this time zone that are of type DAYLIGHT.
149
+ * @deprecated Use {@link getDaylightOffsets} instead.
150
+ */
151
+ daylightOffsets = this.getDaylightOffsets
152
+ }