iobroker.public-holidays 0.0.1
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.
- package/LICENSE +21 -0
- package/README.md +50 -0
- package/admin/i18n/de/translations.json +8 -0
- package/admin/i18n/en/translations.json +8 -0
- package/admin/i18n/es/translations.json +5 -0
- package/admin/i18n/fr/translations.json +5 -0
- package/admin/i18n/it/translations.json +5 -0
- package/admin/i18n/nl/translations.json +5 -0
- package/admin/i18n/pl/translations.json +5 -0
- package/admin/i18n/pt/translations.json +5 -0
- package/admin/i18n/ru/translations.json +5 -0
- package/admin/i18n/uk/translations.json +5 -0
- package/admin/i18n/zh-cn/translations.json +5 -0
- package/admin/jsonConfig.json +44 -0
- package/admin/public-holidays.webp +0 -0
- package/io-package.json +333 -0
- package/lib/adapter-config.d.ts +19 -0
- package/lib/holidays/at.json +14 -0
- package/lib/holidays/de.json +370 -0
- package/main.js +342 -0
- package/package.json +77 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Jey Cee <iobroker@all-smart.net>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+

|
|
2
|
+
# ioBroker.public-holidays
|
|
3
|
+
|
|
4
|
+
[](https://www.npmjs.com/package/iobroker.public-holidays)
|
|
5
|
+
[](https://www.npmjs.com/package/iobroker.public-holidays)
|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
[](https://nodei.co/npm/iobroker.public-holidays/)
|
|
10
|
+
|
|
11
|
+
**Tests:** 
|
|
12
|
+
|
|
13
|
+
## public-holidays adapter for ioBroker
|
|
14
|
+
|
|
15
|
+
Calculates public holidays
|
|
16
|
+
|
|
17
|
+
## Development information
|
|
18
|
+
The date format for holidays is ISO date: YYYY-MM-DD
|
|
19
|
+
|
|
20
|
+
## Changelog
|
|
21
|
+
<!--
|
|
22
|
+
Placeholder for the next version (at the beginning of the line):
|
|
23
|
+
### **WORK IN PROGRESS**
|
|
24
|
+
-->
|
|
25
|
+
|
|
26
|
+
### **WORK IN PROGRESS**
|
|
27
|
+
* (Jey Cee) initial release
|
|
28
|
+
|
|
29
|
+
## License
|
|
30
|
+
MIT License
|
|
31
|
+
|
|
32
|
+
Copyright (c) 2024 Jey Cee <iobroker@all-smart.net>
|
|
33
|
+
|
|
34
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
35
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
36
|
+
in the Software without restriction, including without limitation the rights
|
|
37
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
38
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
39
|
+
furnished to do so, subject to the following conditions:
|
|
40
|
+
|
|
41
|
+
The above copyright notice and this permission notice shall be included in all
|
|
42
|
+
copies or substantial portions of the Software.
|
|
43
|
+
|
|
44
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
45
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
46
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
47
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
48
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
49
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
50
|
+
SOFTWARE.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"public-holidays adapter settings": "Adaptereinstellungen für public-holidays",
|
|
3
|
+
"states": "Bundesländer",
|
|
4
|
+
"calendar": "Kalendarisch",
|
|
5
|
+
"religion": "Religiös",
|
|
6
|
+
"political": "Politisch",
|
|
7
|
+
"Please wait": "Nachdem ändern des Landes bitte warten bis das Fenster neu geladen wurde. Falls die Daten nicht Aktualisiert wurden, das Fenster nochmal neu laden."
|
|
8
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"public-holidays adapter settings": "Adapter settings for public-holidays",
|
|
3
|
+
"states": "Federal states",
|
|
4
|
+
"calendar": "Calendar",
|
|
5
|
+
"religion": "Religion",
|
|
6
|
+
"political": "Political",
|
|
7
|
+
"Please wait": "After changing the country please wait until the window has been reloaded. If the data has not been updated, reload the window again."
|
|
8
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"i18n": true,
|
|
3
|
+
"type": "panel",
|
|
4
|
+
"items": {
|
|
5
|
+
"country": {
|
|
6
|
+
"type": "select",
|
|
7
|
+
"label": "Country",
|
|
8
|
+
"options": [
|
|
9
|
+
{"label": "Germany", "value": "de"},
|
|
10
|
+
{"label": "Austria", "value": "at"},
|
|
11
|
+
{"label": "Switzerland", "value": "ch"},
|
|
12
|
+
{"label": "Italy", "value": "it"}
|
|
13
|
+
],
|
|
14
|
+
"xs": 12,
|
|
15
|
+
"sm": 12,
|
|
16
|
+
"md": 8,
|
|
17
|
+
"lg": 5,
|
|
18
|
+
"xl": 3
|
|
19
|
+
},
|
|
20
|
+
"_hitSave": {
|
|
21
|
+
"type": "staticText",
|
|
22
|
+
"text": "Please wait",
|
|
23
|
+
"style": {"color": "red", "fontWeight": "bolder", "fontSize": "14px"},
|
|
24
|
+
"onChange": {
|
|
25
|
+
"alsoDependsOn": ["country"], "calculateFunc": "setTimeout( () => { const test = () => { document.querySelector('button[aria-label=\"Save\"]').click(); }; test(); setTimeout( () => {window.location.reload()}, 3000)}, 100) "
|
|
26
|
+
},
|
|
27
|
+
"xs": 12,
|
|
28
|
+
"sm": 12,
|
|
29
|
+
"md": 12,
|
|
30
|
+
"lg": 10,
|
|
31
|
+
"xl": 9,
|
|
32
|
+
"newLine": true
|
|
33
|
+
},
|
|
34
|
+
"holidays": {
|
|
35
|
+
"type": "table",
|
|
36
|
+
"noDelete": true,
|
|
37
|
+
"items": [
|
|
38
|
+
{"type": "checkbox", "title": "Enabled", "attr": "enabled"},
|
|
39
|
+
{"type": "text", "readOnly": true, "title": "Name", "attr": "name", "filter": true, "sort": false, "default": ""},
|
|
40
|
+
{"type": "text", "readOnly": true, "title": "states", "attr": "states", "filter": true, "sort": false, "default": ""}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
Binary file
|
package/io-package.json
ADDED
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
{
|
|
2
|
+
"common": {
|
|
3
|
+
"name": "public-holidays",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"news": {
|
|
6
|
+
"0.0.1": {
|
|
7
|
+
"en": "initial release",
|
|
8
|
+
"de": "Erstveröffentlichung",
|
|
9
|
+
"ru": "Начальная версия",
|
|
10
|
+
"pt": "lançamento inicial",
|
|
11
|
+
"nl": "Eerste uitgave",
|
|
12
|
+
"fr": "Première version",
|
|
13
|
+
"it": "Versione iniziale",
|
|
14
|
+
"es": "Versión inicial",
|
|
15
|
+
"pl": "Pierwsze wydanie",
|
|
16
|
+
"uk": "Початкова версія",
|
|
17
|
+
"zh-cn": "首次出版"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"titleLang": {
|
|
21
|
+
"en": "Public Holidays",
|
|
22
|
+
"de": "Feiertage",
|
|
23
|
+
"ru": "Государственные праздники",
|
|
24
|
+
"pt": "Feriados",
|
|
25
|
+
"nl": "Feestdagen",
|
|
26
|
+
"fr": "Jours fériés",
|
|
27
|
+
"it": "Giorni festivi",
|
|
28
|
+
"es": "Días festivos",
|
|
29
|
+
"pl": "Święta państwowe",
|
|
30
|
+
"uk": "Державні свята",
|
|
31
|
+
"zh-cn": "公共假期"
|
|
32
|
+
},
|
|
33
|
+
"desc": {
|
|
34
|
+
"en": "Calculates public holidays",
|
|
35
|
+
"de": "Berechnet Feiertage",
|
|
36
|
+
"ru": "Рассчитывает праздничные дни",
|
|
37
|
+
"pt": "Calcula feriados",
|
|
38
|
+
"nl": "Berekent feestdagen",
|
|
39
|
+
"fr": "Calcule les jours fériés",
|
|
40
|
+
"it": "Calcola i giorni festivi",
|
|
41
|
+
"es": "Calcula los días festivos",
|
|
42
|
+
"pl": "Oblicza święta",
|
|
43
|
+
"uk": "Розраховує державні свята",
|
|
44
|
+
"zh-cn": "计算公共假期"
|
|
45
|
+
},
|
|
46
|
+
"authors": ["Jey Cee <iobroker@all-smart.net>"],
|
|
47
|
+
"keywords": ["public holidays", "holidays", "calendar"],
|
|
48
|
+
"licenseInformation": {
|
|
49
|
+
"type": "free",
|
|
50
|
+
"license": "MIT"
|
|
51
|
+
},
|
|
52
|
+
"platform": "Javascript/Node.js",
|
|
53
|
+
"icon": "public-holidays.webp",
|
|
54
|
+
"enabled": true,
|
|
55
|
+
"extIcon": "https://raw.githubusercontent.com/Jey Cee/ioBroker.public-holidays/main/admin/public-holidays.webp",
|
|
56
|
+
"readme": "https://github.com/Jey Cee/ioBroker.public-holidays/blob/main/README.md",
|
|
57
|
+
"loglevel": "info",
|
|
58
|
+
"tier": 3,
|
|
59
|
+
"mode": "schedule",
|
|
60
|
+
"schedule": "0 0 * * *",
|
|
61
|
+
"allowInit": true,
|
|
62
|
+
"type": "date-and-time",
|
|
63
|
+
"compact": true,
|
|
64
|
+
"connectionType": "local",
|
|
65
|
+
"dataSource": "poll",
|
|
66
|
+
"adminUI": {
|
|
67
|
+
"config": "json"
|
|
68
|
+
},
|
|
69
|
+
"dependencies": [
|
|
70
|
+
{
|
|
71
|
+
"js-controller": ">=6.0.11"
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
"globalDependencies": [
|
|
75
|
+
{
|
|
76
|
+
"admin": ">=7.0.23"
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
},
|
|
80
|
+
"native": {
|
|
81
|
+
"country": "",
|
|
82
|
+
"holidays": []
|
|
83
|
+
},
|
|
84
|
+
"objects": [],
|
|
85
|
+
"instanceObjects": [
|
|
86
|
+
{
|
|
87
|
+
"_id": "info",
|
|
88
|
+
"type": "channel",
|
|
89
|
+
"common": {
|
|
90
|
+
"name": {
|
|
91
|
+
"en": "Info",
|
|
92
|
+
"de": "Info"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"native": {}
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"_id": "info.lastSettings",
|
|
99
|
+
"type": "state",
|
|
100
|
+
"common": {
|
|
101
|
+
"name": {
|
|
102
|
+
"en": "Last settings",
|
|
103
|
+
"de": "Letzte Einstellungen"
|
|
104
|
+
},
|
|
105
|
+
"desc": {
|
|
106
|
+
"en": "Stores the last settings.",
|
|
107
|
+
"de": "Speichert die Letzten Einstellungen"
|
|
108
|
+
},
|
|
109
|
+
"type": "string",
|
|
110
|
+
"role": "state",
|
|
111
|
+
"read": true,
|
|
112
|
+
"write": false
|
|
113
|
+
},
|
|
114
|
+
"native": {}
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"_id": "today",
|
|
118
|
+
"type": "channel",
|
|
119
|
+
"common": {
|
|
120
|
+
"name": {
|
|
121
|
+
"en": "Today",
|
|
122
|
+
"de": "Heute"
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
"native": {}
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"_id": "today.name",
|
|
129
|
+
"type": "state",
|
|
130
|
+
"common": {
|
|
131
|
+
"name": {
|
|
132
|
+
"en": "Holiday today - Name",
|
|
133
|
+
"de": "Heute Feiertag - Name"
|
|
134
|
+
},
|
|
135
|
+
"desc": {
|
|
136
|
+
"en": "What the holiday is today?",
|
|
137
|
+
"de": "Welcher Feiertag ist heute?"
|
|
138
|
+
},
|
|
139
|
+
"type": "string",
|
|
140
|
+
"role": "state",
|
|
141
|
+
"read": true,
|
|
142
|
+
"write": false
|
|
143
|
+
},
|
|
144
|
+
"native": {}
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"_id": "today.boolean",
|
|
148
|
+
"type": "state",
|
|
149
|
+
"common": {
|
|
150
|
+
"name": {
|
|
151
|
+
"en": "Holiday today?",
|
|
152
|
+
"de": "Heute Feiertag?"
|
|
153
|
+
},
|
|
154
|
+
"desc": {
|
|
155
|
+
"en": "Is the holiday today?",
|
|
156
|
+
"de": "Ist heute Feiertag?"
|
|
157
|
+
},
|
|
158
|
+
"type": "boolean",
|
|
159
|
+
"role": "state",
|
|
160
|
+
"read": true,
|
|
161
|
+
"write": false
|
|
162
|
+
},
|
|
163
|
+
"native": {}
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"_id": "tomorrow",
|
|
167
|
+
"type": "channel",
|
|
168
|
+
"common": {
|
|
169
|
+
"name": {
|
|
170
|
+
"en": "Tomorrow",
|
|
171
|
+
"de": "Morgen"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"native": {}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"_id": "tomorrow.name",
|
|
178
|
+
"type": "state",
|
|
179
|
+
"common": {
|
|
180
|
+
"name": {
|
|
181
|
+
"en": "Holiday tomorrow - Name",
|
|
182
|
+
"de": "Feiertag morgen - Name"
|
|
183
|
+
},
|
|
184
|
+
"desc": {
|
|
185
|
+
"en": "What the holiday is tomorrow?",
|
|
186
|
+
"de": "Welcher Feiertag ist morgen?"
|
|
187
|
+
},
|
|
188
|
+
"type": "string",
|
|
189
|
+
"role": "state",
|
|
190
|
+
"read": true,
|
|
191
|
+
"write": false
|
|
192
|
+
},
|
|
193
|
+
"native": {}
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"_id": "tomorrow.boolean",
|
|
197
|
+
"type": "state",
|
|
198
|
+
"common": {
|
|
199
|
+
"name": {
|
|
200
|
+
"en": "Holiday tomorrow?",
|
|
201
|
+
"de": "Feiertag morgen?"
|
|
202
|
+
},
|
|
203
|
+
"desc": {
|
|
204
|
+
"en": "Is the holiday tomorrow?",
|
|
205
|
+
"de": "Ist der Feiertag morgen?"
|
|
206
|
+
},
|
|
207
|
+
"type": "boolean",
|
|
208
|
+
"role": "state",
|
|
209
|
+
"read": true,
|
|
210
|
+
"write": false
|
|
211
|
+
},
|
|
212
|
+
"native": {}
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
"_id": "aftertomorrow",
|
|
216
|
+
"type": "channel",
|
|
217
|
+
"common": {
|
|
218
|
+
"name": {
|
|
219
|
+
"en": "After tomorrow",
|
|
220
|
+
"de": "Übermorgen"
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"native": {}
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"_id": "aftertomorrow.name",
|
|
227
|
+
"type": "state",
|
|
228
|
+
"common": {
|
|
229
|
+
"name": {
|
|
230
|
+
"en": "Holiday after tomorrow - Name",
|
|
231
|
+
"de": "Feiertag übermorgen - Name"
|
|
232
|
+
},
|
|
233
|
+
"desc": {
|
|
234
|
+
"en": "What the holiday is in the day after tomorrow?",
|
|
235
|
+
"de": "Welcher Feiertag ist übermorgen?"
|
|
236
|
+
},
|
|
237
|
+
"type": "string",
|
|
238
|
+
"role": "state",
|
|
239
|
+
"read": true,
|
|
240
|
+
"write": false
|
|
241
|
+
},
|
|
242
|
+
"native": {}
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"_id": "aftertomorrow.boolean",
|
|
246
|
+
"type": "state",
|
|
247
|
+
"common": {
|
|
248
|
+
"name": {
|
|
249
|
+
"en": "Holiday in the day after tomorrow?",
|
|
250
|
+
"de": "Urlaub übermorgen?"
|
|
251
|
+
},
|
|
252
|
+
"desc": {
|
|
253
|
+
"en": "Is the holiday in the day after tomorrow?",
|
|
254
|
+
"de": "Ist übermorgen Feiertag?"
|
|
255
|
+
},
|
|
256
|
+
"type": "boolean",
|
|
257
|
+
"role": "state",
|
|
258
|
+
"read": true,
|
|
259
|
+
"write": false
|
|
260
|
+
},
|
|
261
|
+
"native": {}
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
"_id": "next",
|
|
265
|
+
"type": "channel",
|
|
266
|
+
"common": {
|
|
267
|
+
"name": {
|
|
268
|
+
"en": "Next holiday",
|
|
269
|
+
"de": "Nächster Feiertag"
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
"native": {}
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"_id": "next.name",
|
|
276
|
+
"type": "state",
|
|
277
|
+
"common": {
|
|
278
|
+
"name": {
|
|
279
|
+
"en": "Next holiday - Name",
|
|
280
|
+
"de": "Nächster Urlaub - Name"
|
|
281
|
+
},
|
|
282
|
+
"desc": {
|
|
283
|
+
"en": "What the holiday is next?",
|
|
284
|
+
"de": "Was ist der nächste Feiertag?"
|
|
285
|
+
},
|
|
286
|
+
"type": "string",
|
|
287
|
+
"role": "state",
|
|
288
|
+
"read": true,
|
|
289
|
+
"write": false
|
|
290
|
+
},
|
|
291
|
+
"native": {}
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
"_id": "next.date",
|
|
295
|
+
"type": "state",
|
|
296
|
+
"common": {
|
|
297
|
+
"name": {
|
|
298
|
+
"en": "Next holiday - date?",
|
|
299
|
+
"de": "Nächster Urlaub - Termin?"
|
|
300
|
+
},
|
|
301
|
+
"desc": {
|
|
302
|
+
"en": "When is the next holiday?",
|
|
303
|
+
"de": "Wann ist der nächste Feiertag?"
|
|
304
|
+
},
|
|
305
|
+
"type": "string",
|
|
306
|
+
"role": "value.date",
|
|
307
|
+
"read": true,
|
|
308
|
+
"write": false
|
|
309
|
+
},
|
|
310
|
+
"native": {}
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"_id": "next.duration",
|
|
314
|
+
"type": "state",
|
|
315
|
+
"common": {
|
|
316
|
+
"name": {
|
|
317
|
+
"en": "Duration till next holiday",
|
|
318
|
+
"de": "Dauer bis zum nächsten Feiertag"
|
|
319
|
+
},
|
|
320
|
+
"desc": {
|
|
321
|
+
"en": "Number of days till next holiday",
|
|
322
|
+
"de": "Anzahl der Tage bis zum nächsten Urlaub"
|
|
323
|
+
},
|
|
324
|
+
"type": "number",
|
|
325
|
+
"role": "value.interval.days",
|
|
326
|
+
"unit": "days",
|
|
327
|
+
"read": true,
|
|
328
|
+
"write": false
|
|
329
|
+
},
|
|
330
|
+
"native": {}
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// This file extends the AdapterConfig type from "@types/iobroker"
|
|
2
|
+
// using the actual properties present in io-package.json
|
|
3
|
+
// in order to provide typings for adapter.config properties
|
|
4
|
+
|
|
5
|
+
import { native } from '../io-package.json';
|
|
6
|
+
|
|
7
|
+
type _AdapterConfig = typeof native;
|
|
8
|
+
|
|
9
|
+
// Augment the globally declared type ioBroker.AdapterConfig
|
|
10
|
+
declare global {
|
|
11
|
+
namespace ioBroker {
|
|
12
|
+
interface AdapterConfig extends _AdapterConfig {
|
|
13
|
+
// Do not enter anything here!
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// this is required so the above AdapterConfig is found by TypeScript / type checking
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "newYear",
|
|
4
|
+
"name": "Neujahr",
|
|
5
|
+
"type": "calendar",
|
|
6
|
+
"date": "01-01",
|
|
7
|
+
"states": "Alle",
|
|
8
|
+
"ruleType": "fixed",
|
|
9
|
+
"offsetDay": null,
|
|
10
|
+
"referenceHoliday": null,
|
|
11
|
+
"weekdayInMonth": null,
|
|
12
|
+
"enabled": true
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"id": "hlThreeKings",
|
|
16
|
+
"name": "Heilige Drei Könige",
|
|
17
|
+
"type": "religion",
|
|
18
|
+
"date": "01-06",
|
|
19
|
+
"states": "Baden-Württemberg, Bayern, Sachsen-Anhalt",
|
|
20
|
+
"ruleType": "fixed",
|
|
21
|
+
"offsetDay": null,
|
|
22
|
+
"referenceHoliday": null,
|
|
23
|
+
"weekdayInMonth": null,
|
|
24
|
+
"enabled": false
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "oldMaids",
|
|
28
|
+
"name": "Weiberfastnacht",
|
|
29
|
+
"type": "calendar",
|
|
30
|
+
"date": null,
|
|
31
|
+
"states": "Alle",
|
|
32
|
+
"ruleType": "easter",
|
|
33
|
+
"offsetDay": -52,
|
|
34
|
+
"referenceHoliday": "easterSunday",
|
|
35
|
+
"weekdayInMonth": null,
|
|
36
|
+
"enabled": false
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"id": "roseMonday",
|
|
40
|
+
"name": "Rosenmontag",
|
|
41
|
+
"type": "calendar",
|
|
42
|
+
"date": null,
|
|
43
|
+
"states": "Alle",
|
|
44
|
+
"ruleType": "easter",
|
|
45
|
+
"offsetDay": -48,
|
|
46
|
+
"referenceHoliday": "easterSunday",
|
|
47
|
+
"weekdayInMonth": null,
|
|
48
|
+
"enabled": false
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "mardiGras",
|
|
52
|
+
"name": "Faschingsdienstag",
|
|
53
|
+
"type": "calendar",
|
|
54
|
+
"date": null,
|
|
55
|
+
"states": "Alle",
|
|
56
|
+
"ruleType": "easter",
|
|
57
|
+
"offsetDay": -47,
|
|
58
|
+
"referenceHoliday": "easterSunday",
|
|
59
|
+
"weekdayInMonth": null,
|
|
60
|
+
"enabled": false
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "ashWednesday",
|
|
64
|
+
"name": "Aschermittwoch",
|
|
65
|
+
"type": "calendar",
|
|
66
|
+
"date": null,
|
|
67
|
+
"states": "Alle",
|
|
68
|
+
"ruleType": "easter",
|
|
69
|
+
"offsetDay": -46,
|
|
70
|
+
"referenceHoliday": "easterSunday",
|
|
71
|
+
"weekdayInMonth": null,
|
|
72
|
+
"enabled": false
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"id": "valentinesDay",
|
|
76
|
+
"name": "Valentinstag",
|
|
77
|
+
"type": "calendar",
|
|
78
|
+
"date": "02-14",
|
|
79
|
+
"states": "Alle",
|
|
80
|
+
"ruleType": "fixed",
|
|
81
|
+
"offsetDay": null,
|
|
82
|
+
"referenceHoliday": null,
|
|
83
|
+
"weekdayInMonth": null,
|
|
84
|
+
"enabled": false
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"id": "intWomansDay",
|
|
88
|
+
"name": "Weltfrauentag",
|
|
89
|
+
"type": "political",
|
|
90
|
+
"date": "03-08",
|
|
91
|
+
"states": "Berlin, Berlin, Mecklenburg-Vorpommern",
|
|
92
|
+
"ruleType": "fixed",
|
|
93
|
+
"offsetDay": null,
|
|
94
|
+
"referenceHoliday": null,
|
|
95
|
+
"weekdayInMonth": null,
|
|
96
|
+
"enabled": false
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"id": "palmSunday",
|
|
100
|
+
"name": "Palmsonntag",
|
|
101
|
+
"type": "religion",
|
|
102
|
+
"date": null,
|
|
103
|
+
"states": "Alle",
|
|
104
|
+
"ruleType": "easter",
|
|
105
|
+
"offsetDay": -7,
|
|
106
|
+
"referenceHoliday": "easterSunday",
|
|
107
|
+
"weekdayInMonth": null,
|
|
108
|
+
"enabled": false
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"id": "holyThursday",
|
|
112
|
+
"name": "Gründonnerstag",
|
|
113
|
+
"type": "religion",
|
|
114
|
+
"date": null,
|
|
115
|
+
"states": "Alle",
|
|
116
|
+
"ruleType": "easter",
|
|
117
|
+
"offsetDay": -3,
|
|
118
|
+
"referenceHoliday": "easterSunday",
|
|
119
|
+
"weekdayInMonth": null,
|
|
120
|
+
"enabled": true
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"id": "goodFriday",
|
|
124
|
+
"name": "Karfreitag",
|
|
125
|
+
"type": "religion",
|
|
126
|
+
"date": null,
|
|
127
|
+
"states": "Alle",
|
|
128
|
+
"ruleType": "easter",
|
|
129
|
+
"offsetDay": -2,
|
|
130
|
+
"referenceHoliday": "easterSunday",
|
|
131
|
+
"weekdayInMonth": null,
|
|
132
|
+
"enabled": true
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"id": "easterSunday",
|
|
136
|
+
"name": "Ostersonntag",
|
|
137
|
+
"type": "religion",
|
|
138
|
+
"date": null,
|
|
139
|
+
"states": "Alle",
|
|
140
|
+
"ruleType": "easter",
|
|
141
|
+
"offsetDay": 0,
|
|
142
|
+
"referenceHoliday": null,
|
|
143
|
+
"weekdayInMonth": null,
|
|
144
|
+
"enabled": true
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"id": "easterMonday",
|
|
148
|
+
"name": "Ostermontag",
|
|
149
|
+
"type": "religion",
|
|
150
|
+
"date": null,
|
|
151
|
+
"states": "Alle",
|
|
152
|
+
"ruleType": "easter",
|
|
153
|
+
"offsetDay": 1,
|
|
154
|
+
"referenceHoliday": "easterSunday",
|
|
155
|
+
"weekdayInMonth": null,
|
|
156
|
+
"enabled": true
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
"id": "walpurgisNight",
|
|
160
|
+
"name": "Walpurgisnacht",
|
|
161
|
+
"type": "calendar",
|
|
162
|
+
"date": "04-30",
|
|
163
|
+
"states": "Alle",
|
|
164
|
+
"ruleType": "fixed",
|
|
165
|
+
"offsetDay": null,
|
|
166
|
+
"referenceHoliday": null,
|
|
167
|
+
"weekdayInMonth": null,
|
|
168
|
+
"enabled": true
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"id": "labourDay",
|
|
172
|
+
"name": "Tag der Arbeit",
|
|
173
|
+
"type": "political",
|
|
174
|
+
"date": "05-01",
|
|
175
|
+
"states": "Alle",
|
|
176
|
+
"ruleType": "fixed",
|
|
177
|
+
"offsetDay": null,
|
|
178
|
+
"referenceHoliday": null,
|
|
179
|
+
"weekdayInMonth": null,
|
|
180
|
+
"enabled": true
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"id": "liberationDay",
|
|
184
|
+
"name": "Tag der Befreiung",
|
|
185
|
+
"type": "political",
|
|
186
|
+
"date": "05-08",
|
|
187
|
+
"states": "Alle",
|
|
188
|
+
"ruleType": "fixed",
|
|
189
|
+
"offsetDay": null,
|
|
190
|
+
"referenceHoliday": null,
|
|
191
|
+
"weekdayInMonth": null,
|
|
192
|
+
"enabled": true
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"id": "ascensionOfChrist",
|
|
196
|
+
"name": "Christi Himmelfahrt (Vatertag)",
|
|
197
|
+
"type": "religion",
|
|
198
|
+
"date": null,
|
|
199
|
+
"states": "Alle",
|
|
200
|
+
"ruleType": "easter",
|
|
201
|
+
"offsetDay": 39,
|
|
202
|
+
"referenceHoliday": "easterSunday",
|
|
203
|
+
"weekdayInMonth": null,
|
|
204
|
+
"enabled": true
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
"id": "mothersDay",
|
|
208
|
+
"name": "Muttertag",
|
|
209
|
+
"type": "calendar",
|
|
210
|
+
"date": null,
|
|
211
|
+
"states": "Alle",
|
|
212
|
+
"ruleType": "weekdayInMonth",
|
|
213
|
+
"offsetDay": null,
|
|
214
|
+
"referenceHoliday": null,
|
|
215
|
+
"weekdayInMonth": {
|
|
216
|
+
"weekday": 0,
|
|
217
|
+
"week": 2,
|
|
218
|
+
"month": 5
|
|
219
|
+
},
|
|
220
|
+
"enabled": true
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
"id": "whitSunday",
|
|
224
|
+
"name": "Pfingstsonntag",
|
|
225
|
+
"type": "religion",
|
|
226
|
+
"date": null,
|
|
227
|
+
"states": "Alle",
|
|
228
|
+
"ruleType": "easter",
|
|
229
|
+
"offsetDay": 49,
|
|
230
|
+
"referenceHoliday": "easterSunday",
|
|
231
|
+
"weekdayInMonth": null,
|
|
232
|
+
"enabled": true
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"id": "whitSunday",
|
|
236
|
+
"name": "Pfingstmontag",
|
|
237
|
+
"type": "religion",
|
|
238
|
+
"date": null,
|
|
239
|
+
"states": "Alle",
|
|
240
|
+
"ruleType": "easter",
|
|
241
|
+
"offsetDay": 50,
|
|
242
|
+
"referenceHoliday": "easterSunday",
|
|
243
|
+
"weekdayInMonth": null,
|
|
244
|
+
"enabled": true
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"id": "feastDay",
|
|
248
|
+
"name": "Fronleichnam",
|
|
249
|
+
"type": "religion",
|
|
250
|
+
"date": null,
|
|
251
|
+
"states": "Baden-Württemberg, Bayern, Hessen, Nordrhein-Westfalen, Rheinland-Pfalz, Saarland, Sachsen, Thüringen",
|
|
252
|
+
"ruleType": "easter",
|
|
253
|
+
"offsetDay": 60,
|
|
254
|
+
"referenceHoliday": "easterSunday",
|
|
255
|
+
"weekdayInMonth": null,
|
|
256
|
+
"enabled": true
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"id": "peaceDayAugsburg",
|
|
260
|
+
"name": "Friedensfest Augsburg",
|
|
261
|
+
"type": "religion",
|
|
262
|
+
"date": "08-08",
|
|
263
|
+
"states": "Bayern",
|
|
264
|
+
"ruleType": "fixed",
|
|
265
|
+
"offsetDay": null,
|
|
266
|
+
"referenceHoliday": null,
|
|
267
|
+
"weekdayInMonth": null,
|
|
268
|
+
"enabled": true
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"id": "assumptionOfMary",
|
|
272
|
+
"name": "Mariä Himmelfahrt",
|
|
273
|
+
"type": "religion",
|
|
274
|
+
"date": "08-15",
|
|
275
|
+
"states": "Bayern, Saarland",
|
|
276
|
+
"ruleType": "fixed",
|
|
277
|
+
"offsetDay": null,
|
|
278
|
+
"referenceHoliday": null,
|
|
279
|
+
"weekdayInMonth": null,
|
|
280
|
+
"enabled": true
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
"id": "worldsChildDay",
|
|
284
|
+
"name": "Weltkindertag",
|
|
285
|
+
"type": "calendar",
|
|
286
|
+
"date": "09-20",
|
|
287
|
+
"states": "Thüringen",
|
|
288
|
+
"ruleType": "fixed",
|
|
289
|
+
"offsetDay": null,
|
|
290
|
+
"referenceHoliday": null,
|
|
291
|
+
"weekdayInMonth": null,
|
|
292
|
+
"enabled": true
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
"id": "germanUnity",
|
|
296
|
+
"name": "Tag der Deutschen Einheit",
|
|
297
|
+
"type": "political",
|
|
298
|
+
"date": "10-03",
|
|
299
|
+
"states": "Alle",
|
|
300
|
+
"ruleType": "fixed",
|
|
301
|
+
"offsetDay": null,
|
|
302
|
+
"referenceHoliday": null,
|
|
303
|
+
"weekdayInMonth": null,
|
|
304
|
+
"enabled": true
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
"id": "reformationDay",
|
|
308
|
+
"name": "Reformationstag/-fest",
|
|
309
|
+
"type": "political",
|
|
310
|
+
"date": "10-31",
|
|
311
|
+
"states": "Brandenburg, Bremen, Hamburg, BerlinMecklenburg-Vorpommern, NI, Sachsen, Schleswig-Holstein, Sachsen-Anhalt, Thüringen",
|
|
312
|
+
"ruleType": "fixed",
|
|
313
|
+
"offsetDay": null,
|
|
314
|
+
"referenceHoliday": null,
|
|
315
|
+
"weekdayInMonth": null,
|
|
316
|
+
"enabled": true
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"id": "allSaints",
|
|
320
|
+
"name": "Allerheiligen",
|
|
321
|
+
"type": "religion",
|
|
322
|
+
"date": "11-01",
|
|
323
|
+
"states": "Brandenburg, Bayern, Nordrhein-Westfalen, Rheinland-Pfalz, Saarland",
|
|
324
|
+
"ruleType": "fixed",
|
|
325
|
+
"offsetDay": null,
|
|
326
|
+
"referenceHoliday": null,
|
|
327
|
+
"weekdayInMonth": null,
|
|
328
|
+
"enabled": true
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
"id": "penanceDay",
|
|
332
|
+
"name": "Buß- und Bettag",
|
|
333
|
+
"type": "religion",
|
|
334
|
+
"date": null,
|
|
335
|
+
"states": "Alle",
|
|
336
|
+
"ruleType": "weekdayInMonth",
|
|
337
|
+
"offsetDay": null,
|
|
338
|
+
"referenceHoliday": null,
|
|
339
|
+
"weekdayInMonth": {
|
|
340
|
+
"weekday": 3,
|
|
341
|
+
"week": 3,
|
|
342
|
+
"month": 11
|
|
343
|
+
},
|
|
344
|
+
"enabled": true
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
"id": "firstChristmasDay",
|
|
348
|
+
"name": "1. Weihnachtsfeiertag",
|
|
349
|
+
"type": "religion",
|
|
350
|
+
"date": "12-25",
|
|
351
|
+
"states": "Alle",
|
|
352
|
+
"ruleType": "fixed",
|
|
353
|
+
"offsetDay": null,
|
|
354
|
+
"referenceHoliday": null,
|
|
355
|
+
"weekdayInMonth": null,
|
|
356
|
+
"enabled": true
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
"id": "secondChristmasDay",
|
|
360
|
+
"name": "2. Weihnachtsfeiertag",
|
|
361
|
+
"type": "religion",
|
|
362
|
+
"date": "12-26",
|
|
363
|
+
"states": "Alle",
|
|
364
|
+
"ruleType": "fixed",
|
|
365
|
+
"offsetDay": null,
|
|
366
|
+
"referenceHoliday": null,
|
|
367
|
+
"weekdayInMonth": null,
|
|
368
|
+
"enabled": true
|
|
369
|
+
}
|
|
370
|
+
]
|
package/main.js
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Created with @iobroker/create-adapter v2.6.5
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// The adapter-core module gives you access to the core ioBroker functions
|
|
8
|
+
// you need to create an adapter
|
|
9
|
+
const utils = require('@iobroker/adapter-core');
|
|
10
|
+
|
|
11
|
+
// Load your modules here, e.g.:
|
|
12
|
+
const deHolidays = require('./lib/holidays/de.json');
|
|
13
|
+
const atHolidays = require('./lib/holidays/at.json');
|
|
14
|
+
|
|
15
|
+
class PublicHolidays extends utils.Adapter {
|
|
16
|
+
/**
|
|
17
|
+
* @param {Partial<utils.AdapterOptions>} [options={}]
|
|
18
|
+
*/
|
|
19
|
+
constructor(options) {
|
|
20
|
+
super({
|
|
21
|
+
...options,
|
|
22
|
+
name: 'public-holidays',
|
|
23
|
+
});
|
|
24
|
+
this.on('ready', this.onReady.bind(this));
|
|
25
|
+
this.on('stateChange', this.onStateChange.bind(this));
|
|
26
|
+
// this.on('objectChange', this.onObjectChange.bind(this));
|
|
27
|
+
// this.on('message', this.onMessage.bind(this));
|
|
28
|
+
this.on('unload', this.onUnload.bind(this));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Is called when databases are connected and adapter received configuration.
|
|
33
|
+
*/
|
|
34
|
+
async onReady() {
|
|
35
|
+
updateSettings: if (this.config.country !== '') {
|
|
36
|
+
try {
|
|
37
|
+
const lastSettingsState = await this.getStateAsync(`info.lastSettings`);
|
|
38
|
+
let lastSettings;
|
|
39
|
+
if (lastSettingsState && lastSettingsState.val) {
|
|
40
|
+
lastSettings = lastSettingsState.val;
|
|
41
|
+
}
|
|
42
|
+
if (JSON.stringify(lastSettings) === JSON.stringify(this.config)) {
|
|
43
|
+
break updateSettings;
|
|
44
|
+
}
|
|
45
|
+
const adapterObject = await this.getForeignObjectAsync(
|
|
46
|
+
'system.adapter.public-holidays.' + this.instance
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (adapterObject === null || adapterObject === undefined) {
|
|
50
|
+
break updateSettings;
|
|
51
|
+
}
|
|
52
|
+
// Load original Settings after changing country
|
|
53
|
+
if (adapterObject.native.country !== lastSettings.country) {
|
|
54
|
+
|
|
55
|
+
delete adapterObject.native['holidays'];
|
|
56
|
+
switch (this.config.country) {
|
|
57
|
+
case 'de':
|
|
58
|
+
adapterObject.native['holidays'] = deHolidays;
|
|
59
|
+
await this.setState(`info.lastSettings`, { val: adapterObject.native, ack: true });
|
|
60
|
+
await this.setForeignObjectAsync(
|
|
61
|
+
'system.adapter.public-holidays.' + this.instance,
|
|
62
|
+
adapterObject,
|
|
63
|
+
);
|
|
64
|
+
break;
|
|
65
|
+
case 'at':
|
|
66
|
+
adapterObject.native['holidays'] = atHolidays;
|
|
67
|
+
await this.setState(`info.lastSettings`, { val: adapterObject.native, ack: true });
|
|
68
|
+
await this.setForeignObjectAsync(
|
|
69
|
+
'system.adapter.public-holidays.' + this.instance,
|
|
70
|
+
adapterObject,
|
|
71
|
+
);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
} else {
|
|
75
|
+
await this.setState(`info.lastSettings`, { val: adapterObject.native, ack: true });
|
|
76
|
+
}
|
|
77
|
+
} catch (error) {
|
|
78
|
+
console.error(error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Check if one or more enabled holidays are today
|
|
83
|
+
|
|
84
|
+
const today = new Date();
|
|
85
|
+
// const today = new Date('2024-05-12T10:16:30.577Z');
|
|
86
|
+
const tomorrow = new Date(today);
|
|
87
|
+
tomorrow.setDate(today.getDate() + 1);
|
|
88
|
+
const afterTomorrow = new Date(today);
|
|
89
|
+
afterTomorrow.setDate(today.getDate() + 2);
|
|
90
|
+
|
|
91
|
+
const holidays = this.config.holidays;
|
|
92
|
+
|
|
93
|
+
let todayBoolean = false;
|
|
94
|
+
let todayName = '';
|
|
95
|
+
let tomorrowBoolean = false;
|
|
96
|
+
let tomorrowName = '';
|
|
97
|
+
let afterTomorrowBoolean = false;
|
|
98
|
+
let afterTomorrowName = '';
|
|
99
|
+
|
|
100
|
+
// Loop through each holiday and check if it matches today
|
|
101
|
+
for (const holiday of holidays) {
|
|
102
|
+
if (holiday.enabled) {
|
|
103
|
+
const holidayTodayDate = calculateHoliday(holiday, today.getFullYear());
|
|
104
|
+
// Check if today is holiday
|
|
105
|
+
if (holidayTodayDate instanceof Date && holidayTodayDate.toDateString() === today.toDateString()) {
|
|
106
|
+
todayBoolean = true;
|
|
107
|
+
if (todayName.length === 0) {
|
|
108
|
+
todayName = holiday.name;
|
|
109
|
+
} else {
|
|
110
|
+
todayName += `, ${holiday.name}`;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// Check if tomorrow is holiday
|
|
114
|
+
const holidayTomorrowDate = calculateHoliday(holiday, tomorrow.getFullYear());
|
|
115
|
+
if (
|
|
116
|
+
holidayTomorrowDate instanceof Date &&
|
|
117
|
+
holidayTomorrowDate.toDateString() === tomorrow.toDateString()
|
|
118
|
+
) {
|
|
119
|
+
tomorrowBoolean = true;
|
|
120
|
+
if (tomorrowName.length === 0) {
|
|
121
|
+
tomorrowName = holiday.name;
|
|
122
|
+
} else {
|
|
123
|
+
tomorrowName += `, ${tomorrowName}`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Check if after tomorrow is holiday
|
|
127
|
+
const holidayAfterTomorrowDate = calculateHoliday(holiday, afterTomorrow.getFullYear());
|
|
128
|
+
if (
|
|
129
|
+
holidayAfterTomorrowDate instanceof Date &&
|
|
130
|
+
holidayAfterTomorrowDate.toDateString() === afterTomorrow.toDateString()
|
|
131
|
+
) {
|
|
132
|
+
afterTomorrowBoolean = true;
|
|
133
|
+
if (afterTomorrowName.length === 0) {
|
|
134
|
+
afterTomorrowName = holiday.name;
|
|
135
|
+
} else {
|
|
136
|
+
afterTomorrowName += `, ${afterTomorrowName}`;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Find the next holiday
|
|
143
|
+
const findNextHoliday = (year) => {
|
|
144
|
+
return holidays
|
|
145
|
+
.filter((holiday) => holiday.enabled)
|
|
146
|
+
.map((holiday) => calculateHoliday(holiday, year))
|
|
147
|
+
.filter((date) => date instanceof Date && date >= today) // Future dates
|
|
148
|
+
.sort((a, b) => a - b)[0];
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
let year = today.getFullYear();
|
|
152
|
+
|
|
153
|
+
let nextHoliday = findNextHoliday(year);
|
|
154
|
+
|
|
155
|
+
if (!nextHoliday) {
|
|
156
|
+
year = today.getFullYear() + 1;
|
|
157
|
+
// No holiday found in the current year, try the next year
|
|
158
|
+
nextHoliday = findNextHoliday(year);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (nextHoliday) {
|
|
162
|
+
const daysUntilNextHoliday = Math.ceil((nextHoliday - today) / (1000 * 60 * 60 * 24));
|
|
163
|
+
const nextHolidayName = holidays.find(
|
|
164
|
+
(holiday) =>
|
|
165
|
+
calculateHoliday(holiday, year)?.toDateString() ===
|
|
166
|
+
nextHoliday.toDateString(),
|
|
167
|
+
).name;
|
|
168
|
+
|
|
169
|
+
this.setStateChanged(`next.name`, { val: nextHolidayName, ack: true });
|
|
170
|
+
this.setStateChanged(`next.date`, { val: nextHoliday.toLocaleDateString(), ack: true });
|
|
171
|
+
this.setStateChanged(`next.duration`, { val: daysUntilNextHoliday, ack: true });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
this.setStateChanged(`today.name`, { val: todayName, ack: true });
|
|
175
|
+
this.setStateChanged(`today.boolean`, {val: todayBoolean, ack: true});
|
|
176
|
+
this.setStateChanged(`tomorrow.name`, { val: tomorrowName, ack: true });
|
|
177
|
+
this.setStateChanged(`tomorrow.boolean`, {val: tomorrowBoolean, ack: true});
|
|
178
|
+
this.setStateChanged(`aftertomorrow.name`, { val: afterTomorrowName, ack: true });
|
|
179
|
+
this.setStateChanged(`aftertomorrow.boolean`, {val: afterTomorrowBoolean, ack: true});
|
|
180
|
+
|
|
181
|
+
this.stop({ exitCode: 0 });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Is called when adapter shuts down - callback has to be called under any circumstances!
|
|
186
|
+
* @param {() => void} callback
|
|
187
|
+
*/
|
|
188
|
+
onUnload(callback) {
|
|
189
|
+
try {
|
|
190
|
+
// Here you must clear all timeouts or intervals that may still be active
|
|
191
|
+
// clearTimeout(timeout1);
|
|
192
|
+
// clearTimeout(timeout2);
|
|
193
|
+
// ...
|
|
194
|
+
// clearInterval(interval1);
|
|
195
|
+
|
|
196
|
+
callback();
|
|
197
|
+
} catch (e) {
|
|
198
|
+
callback();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// If you need to react to object changes, uncomment the following block and the corresponding line in the constructor.
|
|
203
|
+
// You also need to subscribe to the objects with `this.subscribeObjects`, similar to `this.subscribeStates`.
|
|
204
|
+
// /**
|
|
205
|
+
// * Is called if a subscribed object changes
|
|
206
|
+
// * @param {string} id
|
|
207
|
+
// * @param {ioBroker.Object | null | undefined} obj
|
|
208
|
+
// */
|
|
209
|
+
// onObjectChange(id, obj) {
|
|
210
|
+
// if (obj) {
|
|
211
|
+
// // The object was changed
|
|
212
|
+
// this.log.info(`object ${id} changed: ${JSON.stringify(obj)}`);
|
|
213
|
+
// } else {
|
|
214
|
+
// // The object was deleted
|
|
215
|
+
// this.log.info(`object ${id} deleted`);
|
|
216
|
+
// }
|
|
217
|
+
// }
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Is called if a subscribed state changes
|
|
221
|
+
* @param {string} id
|
|
222
|
+
* @param {ioBroker.State | null | undefined} state
|
|
223
|
+
*/
|
|
224
|
+
onStateChange(id, state) {
|
|
225
|
+
if (state) {
|
|
226
|
+
// The state was changed
|
|
227
|
+
this.log.info(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
|
|
228
|
+
} else {
|
|
229
|
+
// The state was deleted
|
|
230
|
+
this.log.info(`state ${id} deleted`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// If you need to accept messages in your adapter, uncomment the following block and the corresponding line in the constructor.
|
|
235
|
+
// /**
|
|
236
|
+
// * Some message was sent to this instance over message box. Used by email, pushover, text2speech, ...
|
|
237
|
+
// * Using this method requires "common.messagebox" property to be set to true in io-package.json
|
|
238
|
+
// * @param {ioBroker.Message} obj
|
|
239
|
+
// */
|
|
240
|
+
// onMessage(obj) {
|
|
241
|
+
// if (typeof obj === 'object' && obj.message) {
|
|
242
|
+
// if (obj.command === 'send') {
|
|
243
|
+
// // e.g. send email or pushover or whatever
|
|
244
|
+
// this.log.info('send command');
|
|
245
|
+
|
|
246
|
+
// // Send response in callback if required
|
|
247
|
+
// if (obj.callback) this.sendTo(obj.from, obj.command, 'Message received', obj.callback);
|
|
248
|
+
// }
|
|
249
|
+
// }
|
|
250
|
+
// }
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Calculates the date of a holiday based on its rule type and the specified year.
|
|
255
|
+
* @param {Object} holiday - The holiday object containing the rule type and other specific details required for calculation.
|
|
256
|
+
* @param {string} holiday.ruleType - The type of rule used to calculate the holiday (e.g., 'fixed', 'easter', 'weekdayInMonth').
|
|
257
|
+
* @param {string} [holiday.date] - The specific date for fixed holidays in YYYY-MM-DD format.
|
|
258
|
+
* @param {number} [holiday.offsetDays] - The number of days offset from Easter Sunday for 'easter' type holidays.
|
|
259
|
+
* @param {Object} [holiday.weekdayInMonth] - The information for calculating 'weekdayInMonth' type holidays.
|
|
260
|
+
* @param {number} year - The year for which the holiday is to be calculated.
|
|
261
|
+
* @return {Date|null} The calculated date of the holiday, or null if the rule type is not recognized.
|
|
262
|
+
*/
|
|
263
|
+
function calculateHoliday(holiday, year) {
|
|
264
|
+
switch (holiday.ruleType) {
|
|
265
|
+
case 'fixed':
|
|
266
|
+
return new Date(`${year}-${holiday.date}`);
|
|
267
|
+
case 'easter':
|
|
268
|
+
return calculateEasterSunday(year, holiday.offsetDays);
|
|
269
|
+
case 'weekdayInMonth':
|
|
270
|
+
return calculateWeekdayInMonth(year, holiday.weekdayInMonth);
|
|
271
|
+
default:
|
|
272
|
+
console.error ('Can not calculate holiday');
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Calculates the date of Easter Sunday and allows an offset in days.
|
|
279
|
+
*
|
|
280
|
+
* @param {number} year - The year for which to calculate Easter Sunday.
|
|
281
|
+
* @param {number} offsetDays - The number of days to offset from Easter Sunday.
|
|
282
|
+
*
|
|
283
|
+
* @return {Date} The date of Easter Sunday with the specified offset.
|
|
284
|
+
*/
|
|
285
|
+
function calculateEasterSunday(year, offsetDays) {
|
|
286
|
+
|
|
287
|
+
const a = year % 19;
|
|
288
|
+
const b = Math.floor(year / 100);
|
|
289
|
+
const c = year % 100;
|
|
290
|
+
const d = Math.floor(b / 4);
|
|
291
|
+
const e = b % 4;
|
|
292
|
+
const f = Math.floor((b + 8) / 25);
|
|
293
|
+
const g = Math.floor((b - f + 1) / 3);
|
|
294
|
+
const h = (19 * a + b - d - g + 15) % 30;
|
|
295
|
+
const i = Math.floor(c / 4);
|
|
296
|
+
const k = c % 4;
|
|
297
|
+
const l = (32 + 2 * e + 2 * i - h - k) % 7;
|
|
298
|
+
const m = Math.floor((a + 11 * h + 22 * l) / 451);
|
|
299
|
+
const month = Math.floor((h + l - 7 * m + 114) / 31); // 3 = März, 4 = April
|
|
300
|
+
const day = ((h + l - 7 * m + 114) % 31) + 1;
|
|
301
|
+
|
|
302
|
+
const easterSunday = new Date(year, month - 1, day);
|
|
303
|
+
return new Date(easterSunday.setDate(easterSunday.getDate() + offsetDays));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Calculates the date of the nth occurrence of a specific weekday in a given month and year.
|
|
308
|
+
*
|
|
309
|
+
* @param {number} year - The year for which to calculate the date.
|
|
310
|
+
* @param {Object} options - Object containing the details for the calculation.
|
|
311
|
+
* @param {number} options.weekday - The weekday to find (0 for Sunday, 1 for Monday, ..., 6 for Saturday).
|
|
312
|
+
* @param {number} options.week - The occurrence of the weekday in the month (1 for first occurrence, 2 for second, etc.).
|
|
313
|
+
* @param {number} options.month - The month in which to find the weekday (1 for January, 2 for February, ..., 12 for December).
|
|
314
|
+
* @return {Date|null} The date of the nth occurrence of the specified weekday, or null if it doesn't exist.
|
|
315
|
+
*/
|
|
316
|
+
function calculateWeekdayInMonth(year, { weekday, week, month }) {
|
|
317
|
+
const date = new Date(year, month - 1, 1);
|
|
318
|
+
let count = 0;
|
|
319
|
+
|
|
320
|
+
while (date.getMonth() === month - 1) {
|
|
321
|
+
if (date.getDay() === weekday) {
|
|
322
|
+
count++;
|
|
323
|
+
if (count === week) {
|
|
324
|
+
return date;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
date.setDate(date.getDate() + 1);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (require.main !== module) {
|
|
334
|
+
// Export the constructor in compact mode
|
|
335
|
+
/**
|
|
336
|
+
* @param {Partial<utils.AdapterOptions>} [options={}]
|
|
337
|
+
*/
|
|
338
|
+
module.exports = (options) => new PublicHolidays(options);
|
|
339
|
+
} else {
|
|
340
|
+
// otherwise start the instance directly
|
|
341
|
+
new PublicHolidays();
|
|
342
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "iobroker.public-holidays",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Calculates public holidays",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "Jey Cee",
|
|
7
|
+
"email": "iobroker@all-smart.net"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/Jey Cee/ioBroker.public-holidays",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"keywords": [
|
|
12
|
+
"public holidays",
|
|
13
|
+
"holidays",
|
|
14
|
+
"calendar"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/Jey Cee/ioBroker.public-holidays.git"
|
|
19
|
+
},
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">= 20"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@iobroker/adapter-core": "^3.2.2"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@alcalzone/release-script": "^3.8.0",
|
|
28
|
+
"@alcalzone/release-script-plugin-iobroker": "^3.7.2",
|
|
29
|
+
"@alcalzone/release-script-plugin-license": "^3.7.0",
|
|
30
|
+
"@alcalzone/release-script-plugin-manual-review": "^3.7.0",
|
|
31
|
+
"@iobroker/adapter-dev": "^1.3.0",
|
|
32
|
+
"@iobroker/testing": "^5.0.0",
|
|
33
|
+
"@tsconfig/node20": "^20.1.4",
|
|
34
|
+
"@types/chai-as-promised": "^7.1.8",
|
|
35
|
+
"@types/chai": "^4.3.20",
|
|
36
|
+
"@types/mocha": "^10.0.9",
|
|
37
|
+
"@types/node": "^20.16.15",
|
|
38
|
+
"@types/proxyquire": "^1.3.31",
|
|
39
|
+
"@types/sinon": "^17.0.3",
|
|
40
|
+
"@types/sinon-chai": "^3.2.12",
|
|
41
|
+
"chai-as-promised": "^7.1.2",
|
|
42
|
+
"chai": "^4.5.0",
|
|
43
|
+
"eslint-config-prettier": "^9.1.0",
|
|
44
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
45
|
+
"eslint": "^8.57.1",
|
|
46
|
+
"mocha": "^10.7.3",
|
|
47
|
+
"prettier": "^3.3.3",
|
|
48
|
+
"proxyquire": "^2.1.3",
|
|
49
|
+
"sinon": "^19.0.2",
|
|
50
|
+
"sinon-chai": "^3.7.0",
|
|
51
|
+
"typescript": "~5.0.4"
|
|
52
|
+
},
|
|
53
|
+
"main": "main.js",
|
|
54
|
+
"files": [
|
|
55
|
+
"admin{,/!(src)/**}/!(tsconfig|tsconfig.*|.eslintrc).{json,json5}",
|
|
56
|
+
"admin{,/!(src)/**}/*.{html,css,png,svg,jpg,js,webp}",
|
|
57
|
+
"lib/",
|
|
58
|
+
"www/",
|
|
59
|
+
"io-package.json",
|
|
60
|
+
"LICENSE",
|
|
61
|
+
"main.js"
|
|
62
|
+
],
|
|
63
|
+
"scripts": {
|
|
64
|
+
"test:js": "mocha --config test/mocharc.custom.json \"{!(node_modules|test)/**/*.test.js,*.test.js,test/**/test!(PackageFiles|Startup).js}\"",
|
|
65
|
+
"test:package": "mocha test/package --exit",
|
|
66
|
+
"test:integration": "mocha test/integration --exit",
|
|
67
|
+
"test": "npm run test:js && npm run test:package",
|
|
68
|
+
"check": "tsc --noEmit -p tsconfig.check.json",
|
|
69
|
+
"lint": "eslint .",
|
|
70
|
+
"translate": "translate-adapter",
|
|
71
|
+
"release": "release-script"
|
|
72
|
+
},
|
|
73
|
+
"bugs": {
|
|
74
|
+
"url": "https://github.com/Jey Cee/ioBroker.public-holidays/issues"
|
|
75
|
+
},
|
|
76
|
+
"readmeFilename": "README.md"
|
|
77
|
+
}
|