mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-10-28 11:14:58 +00:00
Compare commits
8
Commits
2a72d48468
...
dc2823c1de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dc2823c1de | ||
|
|
304eae34bd | ||
|
|
960e7376fe | ||
|
|
d91cf08b1d | ||
|
|
746e5c5ef3 | ||
|
|
955a6d8c56 | ||
|
|
19187431ce | ||
|
|
cdf6375c71 |
@@ -327,6 +327,7 @@ jobs:
|
||||
repo_token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
title: Development Build v${{steps.build_info.outputs.VERSION}}
|
||||
body: ${{ steps.notes.outputs.BODY }}
|
||||
generate_notes: false
|
||||
automatic_release_tag: 'latest'
|
||||
prerelease: true
|
||||
files: |
|
||||
|
||||
@@ -71,6 +71,8 @@ This release is based on the latest Espressif/Arduino core version 3. It brings
|
||||
- a second boiler monitor `0xE4` carrying `0xFFFF` cleared a valid `pc0Flow`. That empty value is now ignored [#3224](https://github.com/emsesp/EMS-ESP32/issues/3224)
|
||||
- writing a negative custom entity value was always 1 too high because float-to-int rounding always added +0.5. Negative values now round the same way as positive ones [#3297](https://github.com/emsesp/EMS-ESP32/issues/3297)
|
||||
- after a cold boot, SoftAP fallback no longer abandons STA forever. If a home WiFi SSID is configured, EMS-ESP keeps retrying STA while the captive portal is up so a late-booting router (e.g. after a power outage) can still be joined; SoftAP stops once STA gets an IP
|
||||
- NTP time zone strings updated to IANA tz 2026e. About 32 zones had the wrong UTC offset now or within the next year (Mexico no longer uses DST, Egypt does again, Morocco is permanent UTC+0, Kazakhstan, and from 1 November 2026 western Canada stays on permanent offsets). On boot EMS-ESP rewrites the stored POSIX string from the saved IANA label so existing installs pick up the new rules without re-selecting the zone [#3308](https://github.com/emsesp/EMS-ESP32/pull/3308)
|
||||
- MQTT with TLS and a CA certificate crashed on every connect (a boot loop) on boards with PSRAM when the broker's certificate chain is EC, such as Let's Encrypt ISRG Root X2: verifying it needs about 6 KB of stack and the MQTT task only had 5120 bytes. The MQTT task now gets an 8 KB stack when TLS verifies a CA certificate, and keeps 5120 bytes for insecure TLS and plain MQTT
|
||||
|
||||
## Changed
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
"test/test_api/test_api.h",
|
||||
"lib_standalone/**",
|
||||
"pio_local.ini_example",
|
||||
"tz_zones.h",
|
||||
"**/i18n/**",
|
||||
"**/*.js",
|
||||
"**/*.csv",
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"react": "^19.3.1",
|
||||
"react-dom": "^19.3.1",
|
||||
"react-icons": "^5.7.0",
|
||||
"react-router": "^8.4.0",
|
||||
"react-router": "^8.5.0",
|
||||
"typesafe-i18n": "^5.27.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -56,7 +56,7 @@
|
||||
"rollup-plugin-visualizer": "^7.1.1",
|
||||
"terser": "^5.51.2",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.71.2",
|
||||
"typescript-eslint": "^8.72.0",
|
||||
"vite": "^8.3.4",
|
||||
"vite-plugin-imagemin": "^0.6.1"
|
||||
},
|
||||
|
||||
Generated
+88
-80
@@ -203,8 +203,8 @@ importers:
|
||||
specifier: ^5.7.0
|
||||
version: 5.7.0(react@19.3.1)
|
||||
react-router:
|
||||
specifier: ^8.4.0
|
||||
version: 8.4.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1)
|
||||
specifier: ^8.5.0
|
||||
version: 8.5.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)
|
||||
typesafe-i18n:
|
||||
specifier: ^5.27.1
|
||||
version: 5.27.1(typescript@6.0.3)
|
||||
@@ -255,8 +255,8 @@ importers:
|
||||
specifier: ^6.0.3
|
||||
version: 6.0.3
|
||||
typescript-eslint:
|
||||
specifier: ^8.71.2
|
||||
version: 8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
specifier: ^8.72.0
|
||||
version: 8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
vite:
|
||||
specifier: ^8.3.4
|
||||
version: 8.3.4(@types/node@26.6.5)(terser@5.51.2)
|
||||
@@ -873,63 +873,63 @@ packages:
|
||||
'@types/svgo@2.6.4':
|
||||
resolution: {integrity: sha512-l4cmyPEckf8moNYHdJ+4wkHvFxjyW6ulm9l4YGaOxeyBWPhBOT0gvni1InpFPdzx1dKf/2s62qGITwxNWnPQng==}
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.71.2':
|
||||
resolution: {integrity: sha512-K72/pvT7qpm8q3k8G5u93NCSN1RcLxX5h7Gw0bQpbMXviBHeY6Nx1WEwmk9wP+eKTSQ8ecxvcgt/ZX/rB938xQ==}
|
||||
'@typescript-eslint/eslint-plugin@8.72.0':
|
||||
resolution: {integrity: sha512-aysKgysPX9XOv/dk95UkvUDe++Q3n3dJPG9CEWT3RUccxfkPJ+Qn6nhKPDhZXU6Ofo9kgwGWwKyQCnZIXTgngg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
'@typescript-eslint/parser': ^8.71.2
|
||||
'@typescript-eslint/parser': ^8.72.0
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/parser@8.71.2':
|
||||
resolution: {integrity: sha512-aTtmZjp/x3gsGHkDs04/1I8kNogBJkpQaeGaN0PfiG43NzDEmW2n+OP5im9wfsvyX0yP1UZWBrAGtDBfH9jEVw==}
|
||||
'@typescript-eslint/parser@8.72.0':
|
||||
resolution: {integrity: sha512-0O+x3ynciD6zuXb1CKSu165haQV6ey53DKhHHUnujP7U+XlltJG+/keT0Xhd1HXCze+IHf7Tvt39ovyepX/LNw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/project-service@8.71.2':
|
||||
resolution: {integrity: sha512-Pd68GsLVh5ZXlcEccFPdhSOvtHZ/2WU0XsA8zmXOS3F158lVlcTLhfQ6qvtL1RzbMie0Kp8xtbVwAg4nejKPHw==}
|
||||
'@typescript-eslint/project-service@8.72.0':
|
||||
resolution: {integrity: sha512-bzHngBbmIgzj6TsTjVUCntGx6FFLgE7mPjpO0PzHycOaZHXqS43XnrkFIHRS16LLr/xO6FHSXG3GJFo/F4bSBQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/scope-manager@8.71.2':
|
||||
resolution: {integrity: sha512-YF4wgg5iUX5Obywoac27B56FhozMNFhdJSbh11H5GBAwmBtfyRhmgTQqW9tRNNmHDvsZ2CX6UGzoz+YfYn2Leg==}
|
||||
'@typescript-eslint/scope-manager@8.72.0':
|
||||
resolution: {integrity: sha512-JewPyJOYcXBSAS7PIgufscHOwZqhTGyBRiQJhhuDln66tMchxvvt7nJ90JKKIoOelmdHA3kAQbm9cEUHc4JSEA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.71.2':
|
||||
resolution: {integrity: sha512-jz49TAWokm/7yWD9/o837nYax9DyALxIPOImdImvVzo6canBCZYzin8zJyqNR5k1j9K1DE0bVvr0XYB+99uAdg==}
|
||||
'@typescript-eslint/tsconfig-utils@8.72.0':
|
||||
resolution: {integrity: sha512-0vbxCf7xLVPSjcOdm6eQbgViH8EDJ8xnl1laLT9yoqSz2YmcSfSg5Vdl0JUvZf6rcuJ0ZivJIuMD4edTg8obaA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/type-utils@8.71.2':
|
||||
resolution: {integrity: sha512-cC8UaalCViJkb3rH/xLIvidEwoFRtMZMUqDjjJMGEKaTFwYRHYBcoczlEGHuvkHEO8svRDrgZ0yQgOArFmwang==}
|
||||
'@typescript-eslint/type-utils@8.72.0':
|
||||
resolution: {integrity: sha512-gEXxmmbSTSOVTC37IYYvremOM31v+UN2W772bJxmVYPhAOPSUxtacyb7wkm1EhkYKU6KzFJsdU44DCV4to0LWw==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/types@8.71.2':
|
||||
resolution: {integrity: sha512-y5Ukl3oVp7e/VGxqIoEXoeb/Roj71PAJ4WG/N/RGj+eeDvKRLM15kGr9MijLbN0i03S52zxu31Z98E5gWChJKw==}
|
||||
'@typescript-eslint/types@8.72.0':
|
||||
resolution: {integrity: sha512-Adfoy59kxNEjT5E5fnyrp7GpHYuWs8ONbdohu4ez6IU46qDq8LltG90tLmkucZB2uhYL8mqBjtXqGd8yhfjXqQ==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.71.2':
|
||||
resolution: {integrity: sha512-DgNOEsl4pdYzwSL+N/Cl33tX1Hlw3FvId73LnKXfq7jnrF2viOEn7X+P7RBkkSWCVm92gnWd28GIC5vJuLREeA==}
|
||||
'@typescript-eslint/typescript-estree@8.72.0':
|
||||
resolution: {integrity: sha512-gwLfFgWcw15tN2KXDCJvxEOQjPn+P3j/n3eSqkZ5sX4VpW9Cosodr+tWwBZRvJT3TcKx6HnPRGZMCNAiP1Xhug==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/utils@8.71.2':
|
||||
resolution: {integrity: sha512-RyKa1G1M9rKHDhrk+HJtiF1MvLD5Ux2JW3TSkzw+02pRALdpJb+QzG1Y5em+LvCgzGwgg8H7mBRFKljNz7ImPw==}
|
||||
'@typescript-eslint/utils@8.72.0':
|
||||
resolution: {integrity: sha512-0up3oArJZBYnzOaEXKo8DmI43QvMZyPoFEt9LWzRJcyl/RcJjfKKPebknN1VbTgXBf3M/KggUh5uUMdURLnseg==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
typescript: '>=4.8.4 <6.1.0'
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.71.2':
|
||||
resolution: {integrity: sha512-zozlN0UA32bSG2zkKAgQyRYSbEISVoyU6vvkKYo2aSny74D8Jh4e+POkJ6Lk0dlezZi5x7TtD+88Xb06IB8nhg==}
|
||||
'@typescript-eslint/visitor-keys@8.72.0':
|
||||
resolution: {integrity: sha512-E2mroviasaWecDzTGiGMtuEguuLVOeRggnrIn93CJuxYJzQBHbyymlT08aVQydbBal5538o+JkBKXh2sRuCyIA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
acorn-jsx@5.3.2:
|
||||
@@ -1052,8 +1052,8 @@ packages:
|
||||
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
browserslist@4.29.3:
|
||||
resolution: {integrity: sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==}
|
||||
browserslist@4.29.4:
|
||||
resolution: {integrity: sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==}
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
@@ -1872,8 +1872,8 @@ packages:
|
||||
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
ignore@7.0.12:
|
||||
resolution: {integrity: sha512-/8UvqAPU9DGTI9k4mxtf49U37Isfwr8Uts96+SBHIkFxPJnHS0Ew4f00sM4Scd8V8EjM0jUNtVDdv1kPdt35lg==}
|
||||
ignore@7.0.13:
|
||||
resolution: {integrity: sha512-2E8Q6rh+1RRSq/YdaGsNfXsEZy9FVqv6BSSrkmZJP7BnaoPnRfKL+YaofPvP+5rzdk144qSm6i4+hvPgUcbV4Q==}
|
||||
engines: {node: '>= 4'}
|
||||
|
||||
imagemin-gifsicle@7.0.0:
|
||||
@@ -2608,13 +2608,19 @@ packages:
|
||||
react-is@19.3.1:
|
||||
resolution: {integrity: sha512-RRieF6IyxQBkcK6pP8xOHprLTPW6QjRkbGdImtqNme+/hYVwCZkLQLdlZGOhUqXwkS9IEynaGvPJtv6XB/cz0Q==}
|
||||
|
||||
react-router@8.4.0:
|
||||
resolution: {integrity: sha512-JtydAkBvU9UTEe5qNC+POhu+ZBNM7rlKY2IegwXc7Idj7xfRG16x5RZrw3mju+XlqBxfvb2ky9P3jUp9WyWC1g==}
|
||||
react-router@8.5.0:
|
||||
resolution: {integrity: sha512-9nEd/deifcTJIIcUaNIyQGkyXD0D6QVB9XD2O5GgHpP3xu3U5RXm87YQ8++Wn8JQWgMBM/5+PjWPM/7n7O7WHA==}
|
||||
engines: {node: '>=22.22.0'}
|
||||
peerDependencies:
|
||||
'@types/react': '>=19.2.0'
|
||||
'@types/react-dom': '>=19.2.0'
|
||||
react: '>=19.2.7'
|
||||
react-dom: '>=19.2.7'
|
||||
peerDependenciesMeta:
|
||||
'@types/react':
|
||||
optional: true
|
||||
'@types/react-dom':
|
||||
optional: true
|
||||
react-dom:
|
||||
optional: true
|
||||
|
||||
@@ -2996,8 +3002,8 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=3.5.1'
|
||||
|
||||
typescript-eslint@8.71.2:
|
||||
resolution: {integrity: sha512-Rz4effbMy2g9wnvOJZG6SbVavX313Lap1vNEbk1RUochzickvzP8P4HB+bkNg5e50eVz1hQGjh9K1omI1xB4Bw==}
|
||||
typescript-eslint@8.72.0:
|
||||
resolution: {integrity: sha512-r26Fkc8As+mZvqp7SLsMmNFyYUup/6CjK7/eHBHmhOw6GH6n6YFxHVFrG0jN1c5CMpDzelLPxvgeCOzx7BjN+A==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
peerDependencies:
|
||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||
@@ -3224,7 +3230,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/compat-data': 7.29.7
|
||||
'@babel/helper-validator-option': 7.29.7
|
||||
browserslist: 4.29.3
|
||||
browserslist: 4.29.4
|
||||
lru-cache: 5.1.1
|
||||
semver: 6.3.1
|
||||
|
||||
@@ -3796,57 +3802,57 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/node': 26.6.5
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.71.2(@typescript-eslint/parser@8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.72.0(@typescript-eslint/parser@8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@typescript-eslint/parser': 8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.71.2
|
||||
'@typescript-eslint/type-utils': 8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.71.2
|
||||
'@typescript-eslint/parser': 8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.72.0
|
||||
'@typescript-eslint/type-utils': 8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.72.0
|
||||
eslint: 10.13.0(supports-color@10.2.2)
|
||||
ignore: 7.0.12
|
||||
ignore: 7.0.13
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
'@typescript-eslint/parser@8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.71.2
|
||||
'@typescript-eslint/types': 8.71.2
|
||||
'@typescript-eslint/typescript-estree': 8.71.2(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.71.2
|
||||
'@typescript-eslint/scope-manager': 8.72.0
|
||||
'@typescript-eslint/types': 8.72.0
|
||||
'@typescript-eslint/typescript-estree': 8.72.0(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/visitor-keys': 8.72.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
eslint: 10.13.0(supports-color@10.2.2)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/project-service@8.71.2(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
'@typescript-eslint/project-service@8.72.0(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/tsconfig-utils': 8.71.2(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.71.2
|
||||
'@typescript-eslint/tsconfig-utils': 8.72.0(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.72.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/scope-manager@8.71.2':
|
||||
'@typescript-eslint/scope-manager@8.72.0':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.71.2
|
||||
'@typescript-eslint/visitor-keys': 8.71.2
|
||||
'@typescript-eslint/types': 8.72.0
|
||||
'@typescript-eslint/visitor-keys': 8.72.0
|
||||
|
||||
'@typescript-eslint/tsconfig-utils@8.71.2(typescript@6.0.3)':
|
||||
'@typescript-eslint/tsconfig-utils@8.72.0(typescript@6.0.3)':
|
||||
dependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
'@typescript-eslint/type-utils@8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
'@typescript-eslint/type-utils@8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.71.2
|
||||
'@typescript-eslint/typescript-estree': 8.71.2(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.72.0
|
||||
'@typescript-eslint/typescript-estree': 8.72.0(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
eslint: 10.13.0(supports-color@10.2.2)
|
||||
ts-api-utils: 2.5.0(typescript@6.0.3)
|
||||
@@ -3854,14 +3860,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/types@8.71.2': {}
|
||||
'@typescript-eslint/types@8.72.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.71.2(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
'@typescript-eslint/typescript-estree@8.72.0(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/project-service': 8.71.2(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.71.2(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.71.2
|
||||
'@typescript-eslint/visitor-keys': 8.71.2
|
||||
'@typescript-eslint/project-service': 8.72.0(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.72.0(typescript@6.0.3)
|
||||
'@typescript-eslint/types': 8.72.0
|
||||
'@typescript-eslint/visitor-keys': 8.72.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
minimatch: 10.2.6
|
||||
semver: 7.8.5
|
||||
@@ -3871,20 +3877,20 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
'@typescript-eslint/utils@8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@10.13.0(supports-color@10.2.2))
|
||||
'@typescript-eslint/scope-manager': 8.71.2
|
||||
'@typescript-eslint/types': 8.71.2
|
||||
'@typescript-eslint/typescript-estree': 8.71.2(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/scope-manager': 8.72.0
|
||||
'@typescript-eslint/types': 8.72.0
|
||||
'@typescript-eslint/typescript-estree': 8.72.0(supports-color@10.2.2)(typescript@6.0.3)
|
||||
eslint: 10.13.0(supports-color@10.2.2)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/visitor-keys@8.71.2':
|
||||
'@typescript-eslint/visitor-keys@8.72.0':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.71.2
|
||||
'@typescript-eslint/types': 8.72.0
|
||||
eslint-visitor-keys: 5.0.1
|
||||
|
||||
acorn-jsx@5.3.2(acorn@8.19.0):
|
||||
@@ -4006,13 +4012,13 @@ snapshots:
|
||||
dependencies:
|
||||
fill-range: 7.1.1
|
||||
|
||||
browserslist@4.29.3:
|
||||
browserslist@4.29.4:
|
||||
dependencies:
|
||||
baseline-browser-mapping: 2.11.29
|
||||
caniuse-lite: 1.0.30001816
|
||||
electron-to-chromium: 1.5.459
|
||||
node-releases: 2.0.59
|
||||
update-browserslist-db: 1.3.4(browserslist@4.29.3)
|
||||
update-browserslist-db: 1.3.4(browserslist@4.29.4)
|
||||
|
||||
buffer-alloc-unsafe@1.1.0: {}
|
||||
|
||||
@@ -4918,7 +4924,7 @@ snapshots:
|
||||
|
||||
ignore@5.3.2: {}
|
||||
|
||||
ignore@7.0.12: {}
|
||||
ignore@7.0.13: {}
|
||||
|
||||
imagemin-gifsicle@7.0.0:
|
||||
dependencies:
|
||||
@@ -5562,12 +5568,14 @@ snapshots:
|
||||
|
||||
react-is@19.3.1: {}
|
||||
|
||||
react-router@8.4.0(react-dom@19.3.1(react@19.3.1))(react@19.3.1):
|
||||
react-router@8.5.0(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1):
|
||||
dependencies:
|
||||
'@remix-run/route-pattern': 0.22.1
|
||||
cookie-es: 3.1.1
|
||||
react: 19.3.1
|
||||
optionalDependencies:
|
||||
'@types/react': 19.3.0
|
||||
'@types/react-dom': 19.3.0(@types/react@19.3.0)
|
||||
react-dom: 19.3.1(react@19.3.1)
|
||||
|
||||
react-transition-group@4.4.5(react-dom@19.3.1(react@19.3.1))(react@19.3.1):
|
||||
@@ -5936,12 +5944,12 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 6.0.3
|
||||
|
||||
typescript-eslint@8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3):
|
||||
typescript-eslint@8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.71.2(@typescript-eslint/parser@8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/parser': 8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/typescript-estree': 8.71.2(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.71.2(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/eslint-plugin': 8.72.0(@typescript-eslint/parser@8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/parser': 8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/typescript-estree': 8.72.0(supports-color@10.2.2)(typescript@6.0.3)
|
||||
'@typescript-eslint/utils': 8.72.0(eslint@10.13.0(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
|
||||
eslint: 10.13.0(supports-color@10.2.2)
|
||||
typescript: 6.0.3
|
||||
transitivePeerDependencies:
|
||||
@@ -5958,9 +5966,9 @@ snapshots:
|
||||
|
||||
universalify@2.0.1: {}
|
||||
|
||||
update-browserslist-db@1.3.4(browserslist@4.29.3):
|
||||
update-browserslist-db@1.3.4(browserslist@4.29.4):
|
||||
dependencies:
|
||||
browserslist: 4.29.3
|
||||
browserslist: 4.29.4
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
import AccessTimeIcon from '@mui/icons-material/AccessTime';
|
||||
import CancelIcon from '@mui/icons-material/Cancel';
|
||||
@@ -42,6 +42,7 @@ import type { ValidateFieldsError } from 'validators/schema';
|
||||
|
||||
import {
|
||||
TIME_ZONES,
|
||||
migrateNtpTimeZones,
|
||||
selectedTimeZone,
|
||||
timeZoneSelectItemsT,
|
||||
useTimeZoneSelectItems
|
||||
@@ -56,6 +57,7 @@ const NTPSettings = () => {
|
||||
origData,
|
||||
dirtyFlags,
|
||||
setDirtyFlags,
|
||||
setOrigData,
|
||||
blocker,
|
||||
saveData,
|
||||
errorMessage
|
||||
@@ -81,6 +83,31 @@ const NTPSettings = () => {
|
||||
const [settingTime, setSettingTime] = useState<boolean>(false);
|
||||
const [processing, setProcessing] = useState<boolean>(false);
|
||||
const [fieldErrors, setFieldErrors] = useState<ValidateFieldsError>();
|
||||
const migratingTz = useRef(false);
|
||||
|
||||
// If firmware has not yet rewritten tz_format from the label (or the user
|
||||
// landed here before reboot), persist the current TIME_ZONES values quietly.
|
||||
useEffect(() => {
|
||||
if (!data || migratingTz.current || dirtyFlags.length > 0) {
|
||||
return;
|
||||
}
|
||||
const migrated = migrateNtpTimeZones(data);
|
||||
if (!migrated) {
|
||||
return;
|
||||
}
|
||||
migratingTz.current = true;
|
||||
void (async () => {
|
||||
try {
|
||||
updateDataValue(migrated);
|
||||
await NTPApi.updateNTPSettings(migrated);
|
||||
setOrigData(migrated);
|
||||
} catch {
|
||||
// Boot-time firmware migration still applies on the next restart.
|
||||
} finally {
|
||||
migratingTz.current = false;
|
||||
}
|
||||
})();
|
||||
}, [data, dirtyFlags.length, setOrigData, updateDataValue]);
|
||||
|
||||
const { send: updateTime } = useRequest(
|
||||
(local_time: Time) => NTPApi.updateTime(local_time),
|
||||
|
||||
+247
-216
@@ -13,20 +13,20 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'Africa/Blantyre': 'CAT-2',
|
||||
'Africa/Brazzaville': 'WAT-1',
|
||||
'Africa/Bujumbura': 'CAT-2',
|
||||
'Africa/Cairo': 'EET-2',
|
||||
'Africa/Casablanca': 'UNK-1',
|
||||
'Africa/Cairo': 'EET-2EEST,M4.5.5/0,M10.5.4/24',
|
||||
'Africa/Casablanca': '<+00>0',
|
||||
'Africa/Ceuta': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Africa/Conakry': 'GMT0',
|
||||
'Africa/Dakar': 'GMT0',
|
||||
'Africa/Dar_es_Salaam': 'EAT-3',
|
||||
'Africa/Djibouti': 'EAT-3',
|
||||
'Africa/Douala': 'WAT-1',
|
||||
'Africa/El_Aaiun': 'UNK-1',
|
||||
'Africa/El_Aaiun': '<+00>0',
|
||||
'Africa/Freetown': 'GMT0',
|
||||
'Africa/Gaborone': 'CAT-2',
|
||||
'Africa/Harare': 'CAT-2',
|
||||
'Africa/Johannesburg': 'SAST-2',
|
||||
'Africa/Juba': 'EAT-3',
|
||||
'Africa/Juba': 'CAT-2',
|
||||
'Africa/Kampala': 'EAT-3',
|
||||
'Africa/Khartoum': 'CAT-2',
|
||||
'Africa/Kigali': 'CAT-2',
|
||||
@@ -57,42 +57,42 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'America/Anchorage': 'AKST9AKDT,M3.2.0,M11.1.0',
|
||||
'America/Anguilla': 'AST4',
|
||||
'America/Antigua': 'AST4',
|
||||
'America/Araguaina': 'UNK3',
|
||||
'America/Argentina/Buenos_Aires': 'UNK3',
|
||||
'America/Argentina/Catamarca': 'UNK3',
|
||||
'America/Argentina/Cordoba': 'UNK3',
|
||||
'America/Argentina/Jujuy': 'UNK3',
|
||||
'America/Argentina/La_Rioja': 'UNK3',
|
||||
'America/Argentina/Mendoza': 'UNK3',
|
||||
'America/Argentina/Rio_Gallegos': 'UNK3',
|
||||
'America/Argentina/Salta': 'UNK3',
|
||||
'America/Argentina/San_Juan': 'UNK3',
|
||||
'America/Argentina/San_Luis': 'UNK3',
|
||||
'America/Argentina/Tucuman': 'UNK3',
|
||||
'America/Argentina/Ushuaia': 'UNK3',
|
||||
'America/Araguaina': '<-03>3',
|
||||
'America/Argentina/Buenos_Aires': '<-03>3',
|
||||
'America/Argentina/Catamarca': '<-03>3',
|
||||
'America/Argentina/Cordoba': '<-03>3',
|
||||
'America/Argentina/Jujuy': '<-03>3',
|
||||
'America/Argentina/La_Rioja': '<-03>3',
|
||||
'America/Argentina/Mendoza': '<-03>3',
|
||||
'America/Argentina/Rio_Gallegos': '<-03>3',
|
||||
'America/Argentina/Salta': '<-03>3',
|
||||
'America/Argentina/San_Juan': '<-03>3',
|
||||
'America/Argentina/San_Luis': '<-03>3',
|
||||
'America/Argentina/Tucuman': '<-03>3',
|
||||
'America/Argentina/Ushuaia': '<-03>3',
|
||||
'America/Aruba': 'AST4',
|
||||
'America/Asuncion': 'UNK4UNK,M10.1.0/0,M3.4.0/0',
|
||||
'America/Asuncion': '<-03>3',
|
||||
'America/Atikokan': 'EST5',
|
||||
'America/Bahia': 'UNK3',
|
||||
'America/Bahia_Banderas': 'CST6CDT,M4.1.0,M10.5.0',
|
||||
'America/Bahia': '<-03>3',
|
||||
'America/Bahia_Banderas': 'CST6',
|
||||
'America/Barbados': 'AST4',
|
||||
'America/Belem': 'UNK3',
|
||||
'America/Belem': '<-03>3',
|
||||
'America/Belize': 'CST6',
|
||||
'America/Blanc-Sablon': 'AST4',
|
||||
'America/Boa_Vista': 'UNK4',
|
||||
'America/Bogota': 'UNK5',
|
||||
'America/Boa_Vista': '<-04>4',
|
||||
'America/Bogota': '<-05>5',
|
||||
'America/Boise': 'MST7MDT,M3.2.0,M11.1.0',
|
||||
'America/Cambridge_Bay': 'MST7MDT,M3.2.0,M11.1.0',
|
||||
'America/Campo_Grande': 'UNK4',
|
||||
'America/Campo_Grande': '<-04>4',
|
||||
'America/Cancun': 'EST5',
|
||||
'America/Caracas': 'UNK4',
|
||||
'America/Cayenne': 'UNK3',
|
||||
'America/Caracas': '<-04>4',
|
||||
'America/Cayenne': '<-03>3',
|
||||
'America/Cayman': 'EST5',
|
||||
'America/Chicago': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Chihuahua': 'MST7MDT,M4.1.0,M10.5.0',
|
||||
'America/Chihuahua': 'CST6',
|
||||
'America/Costa_Rica': 'CST6',
|
||||
'America/Creston': 'MST7',
|
||||
'America/Cuiaba': 'UNK4',
|
||||
'America/Cuiaba': '<-04>4',
|
||||
'America/Curacao': 'AST4',
|
||||
'America/Danmarkshavn': 'GMT0',
|
||||
'America/Dawson': 'MST7',
|
||||
@@ -100,20 +100,20 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'America/Denver': 'MST7MDT,M3.2.0,M11.1.0',
|
||||
'America/Detroit': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Dominica': 'AST4',
|
||||
'America/Edmonton': 'MST7MDT,M3.2.0,M11.1.0',
|
||||
'America/Eirunepe': 'UNK5',
|
||||
'America/Edmonton': 'CST6',
|
||||
'America/Eirunepe': '<-05>5',
|
||||
'America/El_Salvador': 'CST6',
|
||||
'America/Fort_Nelson': 'MST7',
|
||||
'America/Fortaleza': 'UNK3',
|
||||
'America/Fortaleza': '<-03>3',
|
||||
'America/Glace_Bay': 'AST4ADT,M3.2.0,M11.1.0',
|
||||
'America/Godthab': 'UNK3UNK,M3.5.0/-2,M10.5.0/-1',
|
||||
'America/Godthab': '<-02>2<-01>,M3.5.0/-1,M10.5.0/0',
|
||||
'America/Goose_Bay': 'AST4ADT,M3.2.0,M11.1.0',
|
||||
'America/Grand_Turk': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Grenada': 'AST4',
|
||||
'America/Guadeloupe': 'AST4',
|
||||
'America/Guatemala': 'CST6',
|
||||
'America/Guayaquil': 'UNK5',
|
||||
'America/Guyana': 'UNK4',
|
||||
'America/Guayaquil': '<-05>5',
|
||||
'America/Guyana': '<-04>4',
|
||||
'America/Halifax': 'AST4ADT,M3.2.0,M11.1.0',
|
||||
'America/Havana': 'CST5CDT,M3.2.0/0,M11.1.0/1',
|
||||
'America/Hermosillo': 'MST7',
|
||||
@@ -125,63 +125,63 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'America/Indiana/Vevay': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Indiana/Vincennes': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Indiana/Winamac': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Inuvik': 'MST7MDT,M3.2.0,M11.1.0',
|
||||
'America/Inuvik': 'CST6',
|
||||
'America/Iqaluit': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Jamaica': 'EST5',
|
||||
'America/Juneau': 'AKST9AKDT,M3.2.0,M11.1.0',
|
||||
'America/Kentucky/Louisville': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Kentucky/Monticello': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Kralendijk': 'AST4',
|
||||
'America/La_Paz': 'UNK4',
|
||||
'America/Lima': 'UNK5',
|
||||
'America/La_Paz': '<-04>4',
|
||||
'America/Lima': '<-05>5',
|
||||
'America/Los_Angeles': 'PST8PDT,M3.2.0,M11.1.0',
|
||||
'America/Lower_Princes': 'AST4',
|
||||
'America/Maceio': 'UNK3',
|
||||
'America/Maceio': '<-03>3',
|
||||
'America/Managua': 'CST6',
|
||||
'America/Manaus': 'UNK4',
|
||||
'America/Manaus': '<-04>4',
|
||||
'America/Marigot': 'AST4',
|
||||
'America/Martinique': 'AST4',
|
||||
'America/Matamoros': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Mazatlan': 'MST7MDT,M4.1.0,M10.5.0',
|
||||
'America/Mazatlan': 'MST7',
|
||||
'America/Menominee': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Merida': 'CST6CDT,M4.1.0,M10.5.0',
|
||||
'America/Merida': 'CST6',
|
||||
'America/Metlakatla': 'AKST9AKDT,M3.2.0,M11.1.0',
|
||||
'America/Mexico_City': 'CST6CDT,M4.1.0,M10.5.0',
|
||||
'America/Miquelon': 'UNK3UNK,M3.2.0,M11.1.0',
|
||||
'America/Mexico_City': 'CST6',
|
||||
'America/Miquelon': '<-03>3<-02>,M3.2.0,M11.1.0',
|
||||
'America/Moncton': 'AST4ADT,M3.2.0,M11.1.0',
|
||||
'America/Monterrey': 'CST6CDT,M4.1.0,M10.5.0',
|
||||
'America/Montevideo': 'UNK3',
|
||||
'America/Monterrey': 'CST6',
|
||||
'America/Montevideo': '<-03>3',
|
||||
'America/Montreal': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Montserrat': 'AST4',
|
||||
'America/Nassau': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/New_York': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Nipigon': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Nome': 'AKST9AKDT,M3.2.0,M11.1.0',
|
||||
'America/Noronha': 'UNK2',
|
||||
'America/Noronha': '<-02>2',
|
||||
'America/North_Dakota/Beulah': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/North_Dakota/Center': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/North_Dakota/New_Salem': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Ojinaga': 'MST7MDT,M3.2.0,M11.1.0',
|
||||
'America/Ojinaga': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Panama': 'EST5',
|
||||
'America/Pangnirtung': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Paramaribo': 'UNK3',
|
||||
'America/Paramaribo': '<-03>3',
|
||||
'America/Phoenix': 'MST7',
|
||||
'America/Port-au-Prince': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Port_of_Spain': 'AST4',
|
||||
'America/Porto_Velho': 'UNK4',
|
||||
'America/Porto_Velho': '<-04>4',
|
||||
'America/Puerto_Rico': 'AST4',
|
||||
'America/Punta_Arenas': 'UNK3',
|
||||
'America/Rainy_River': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Punta_Arenas': '<-03>3',
|
||||
'America/Rainy_River': 'EST5',
|
||||
'America/Rankin_Inlet': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Recife': 'UNK3',
|
||||
'America/Recife': '<-03>3',
|
||||
'America/Regina': 'CST6',
|
||||
'America/Resolute': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Rio_Branco': 'UNK5',
|
||||
'America/Santarem': 'UNK3',
|
||||
'America/Santiago': 'UNK4UNK,M9.1.6/24,M4.1.6/24',
|
||||
'America/Rio_Branco': '<-05>5',
|
||||
'America/Santarem': '<-03>3',
|
||||
'America/Santiago': '<-04>4<-03>,M9.1.6/24,M4.1.6/24',
|
||||
'America/Santo_Domingo': 'AST4',
|
||||
'America/Sao_Paulo': 'UNK3',
|
||||
'America/Scoresbysund': 'UNK1UNK,M3.5.0/0,M10.5.0/1',
|
||||
'America/Sao_Paulo': '<-03>3',
|
||||
'America/Scoresbysund': '<-02>2<-01>,M3.5.0/-1,M10.5.0/0',
|
||||
'America/Sitka': 'AKST9AKDT,M3.2.0,M11.1.0',
|
||||
'America/St_Barthelemy': 'AST4',
|
||||
'America/St_Johns': 'NST3:30NDT,M3.2.0,M11.1.0',
|
||||
@@ -196,156 +196,156 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'America/Tijuana': 'PST8PDT,M3.2.0,M11.1.0',
|
||||
'America/Toronto': 'EST5EDT,M3.2.0,M11.1.0',
|
||||
'America/Tortola': 'AST4',
|
||||
'America/Vancouver': 'PST8PDT,M3.2.0,M11.1.0',
|
||||
'America/Vancouver': 'MST7',
|
||||
'America/Whitehorse': 'MST7',
|
||||
'America/Winnipeg': 'CST6CDT,M3.2.0,M11.1.0',
|
||||
'America/Winnipeg': 'EST5',
|
||||
'America/Yakutat': 'AKST9AKDT,M3.2.0,M11.1.0',
|
||||
'America/Yellowknife': 'MST7MDT,M3.2.0,M11.1.0',
|
||||
'Antarctica/Casey': 'UNK-8',
|
||||
'Antarctica/Davis': 'UNK-7',
|
||||
'Antarctica/DumontDUrville': 'UNK-10',
|
||||
'Antarctica/Macquarie': 'UNK-11',
|
||||
'Antarctica/Mawson': 'UNK-5',
|
||||
'America/Yellowknife': 'CST6',
|
||||
'Antarctica/Casey': '<+08>-8',
|
||||
'Antarctica/Davis': '<+07>-7',
|
||||
'Antarctica/DumontDUrville': '<+10>-10',
|
||||
'Antarctica/Macquarie': 'AEST-10AEDT,M10.1.0,M4.1.0/3',
|
||||
'Antarctica/Mawson': '<+05>-5',
|
||||
'Antarctica/McMurdo': 'NZST-12NZDT,M9.5.0,M4.1.0/3',
|
||||
'Antarctica/Palmer': 'UNK3',
|
||||
'Antarctica/Rothera': 'UNK3',
|
||||
'Antarctica/Syowa': 'UNK-3',
|
||||
'Antarctica/Troll': 'UNK0UNK-2,M3.5.0/1,M10.5.0/3',
|
||||
'Antarctica/Vostok': 'UNK-6',
|
||||
'Antarctica/Palmer': '<-03>3',
|
||||
'Antarctica/Rothera': '<-03>3',
|
||||
'Antarctica/Syowa': '<+03>-3',
|
||||
'Antarctica/Troll': '<+00>0<+02>-2,M3.5.0/1,M10.5.0/3',
|
||||
'Antarctica/Vostok': '<+05>-5',
|
||||
'Arctic/Longyearbyen': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Asia/Aden': 'UNK-3',
|
||||
'Asia/Almaty': 'UNK-6',
|
||||
'Asia/Amman': 'EET-2EEST,M3.5.4/24,M10.5.5/1',
|
||||
'Asia/Anadyr': 'UNK-12',
|
||||
'Asia/Aqtau': 'UNK-5',
|
||||
'Asia/Aqtobe': 'UNK-5',
|
||||
'Asia/Ashgabat': 'UNK-5',
|
||||
'Asia/Atyrau': 'UNK-5',
|
||||
'Asia/Baghdad': 'UNK-3',
|
||||
'Asia/Bahrain': 'UNK-3',
|
||||
'Asia/Baku': 'UNK-4',
|
||||
'Asia/Bangkok': 'UNK-7',
|
||||
'Asia/Barnaul': 'UNK-7',
|
||||
'Asia/Aden': '<+03>-3',
|
||||
'Asia/Almaty': '<+05>-5',
|
||||
'Asia/Amman': '<+03>-3',
|
||||
'Asia/Anadyr': '<+12>-12',
|
||||
'Asia/Aqtau': '<+05>-5',
|
||||
'Asia/Aqtobe': '<+05>-5',
|
||||
'Asia/Ashgabat': '<+05>-5',
|
||||
'Asia/Atyrau': '<+05>-5',
|
||||
'Asia/Baghdad': '<+03>-3',
|
||||
'Asia/Bahrain': '<+03>-3',
|
||||
'Asia/Baku': '<+04>-4',
|
||||
'Asia/Bangkok': '<+07>-7',
|
||||
'Asia/Barnaul': '<+07>-7',
|
||||
'Asia/Beirut': 'EET-2EEST,M3.5.0/0,M10.5.0/0',
|
||||
'Asia/Bishkek': 'UNK-6',
|
||||
'Asia/Brunei': 'UNK-8',
|
||||
'Asia/Chita': 'UNK-9',
|
||||
'Asia/Choibalsan': 'UNK-8',
|
||||
'Asia/Colombo': 'UNK-5:30',
|
||||
'Asia/Damascus': 'EET-2EEST,M3.5.5/0,M10.5.5/0',
|
||||
'Asia/Dhaka': 'UNK-6',
|
||||
'Asia/Dili': 'UNK-9',
|
||||
'Asia/Dubai': 'UNK-4',
|
||||
'Asia/Dushanbe': 'UNK-5',
|
||||
'Asia/Bishkek': '<+06>-6',
|
||||
'Asia/Brunei': '<+08>-8',
|
||||
'Asia/Chita': '<+09>-9',
|
||||
'Asia/Choibalsan': '<+08>-8',
|
||||
'Asia/Colombo': '<+0530>-5:30',
|
||||
'Asia/Damascus': '<+03>-3',
|
||||
'Asia/Dhaka': '<+06>-6',
|
||||
'Asia/Dili': '<+09>-9',
|
||||
'Asia/Dubai': '<+04>-4',
|
||||
'Asia/Dushanbe': '<+05>-5',
|
||||
'Asia/Famagusta': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Asia/Gaza': 'EET-2EEST,M3.5.5/0,M10.5.6/1',
|
||||
'Asia/Hebron': 'EET-2EEST,M3.5.5/0,M10.5.6/1',
|
||||
'Asia/Ho_Chi_Minh': 'UNK-7',
|
||||
'Asia/Gaza': 'EET-2EEST,M3.4.4/50,M10.4.4/50',
|
||||
'Asia/Hebron': 'EET-2EEST,M3.4.4/50,M10.4.4/50',
|
||||
'Asia/Ho_Chi_Minh': '<+07>-7',
|
||||
'Asia/Hong_Kong': 'HKT-8',
|
||||
'Asia/Hovd': 'UNK-7',
|
||||
'Asia/Irkutsk': 'UNK-8',
|
||||
'Asia/Hovd': '<+07>-7',
|
||||
'Asia/Irkutsk': '<+08>-8',
|
||||
'Asia/Jakarta': 'WIB-7',
|
||||
'Asia/Jayapura': 'WIT-9',
|
||||
'Asia/Jerusalem': 'IST-2IDT,M3.4.4/26,M10.5.0',
|
||||
'Asia/Kabul': 'UNK-4:30',
|
||||
'Asia/Kamchatka': 'UNK-12',
|
||||
'Asia/Kabul': '<+0430>-4:30',
|
||||
'Asia/Kamchatka': '<+12>-12',
|
||||
'Asia/Karachi': 'PKT-5',
|
||||
'Asia/Kathmandu': 'UNK-5:45',
|
||||
'Asia/Khandyga': 'UNK-9',
|
||||
'Asia/Kathmandu': '<+0545>-5:45',
|
||||
'Asia/Khandyga': '<+09>-9',
|
||||
'Asia/Kolkata': 'IST-5:30',
|
||||
'Asia/Krasnoyarsk': 'UNK-7',
|
||||
'Asia/Kuala_Lumpur': 'UNK-8',
|
||||
'Asia/Kuching': 'UNK-8',
|
||||
'Asia/Kuwait': 'UNK-3',
|
||||
'Asia/Krasnoyarsk': '<+07>-7',
|
||||
'Asia/Kuala_Lumpur': '<+08>-8',
|
||||
'Asia/Kuching': '<+08>-8',
|
||||
'Asia/Kuwait': '<+03>-3',
|
||||
'Asia/Macau': 'CST-8',
|
||||
'Asia/Magadan': 'UNK-11',
|
||||
'Asia/Magadan': '<+11>-11',
|
||||
'Asia/Makassar': 'WITA-8',
|
||||
'Asia/Manila': 'PST-8',
|
||||
'Asia/Muscat': 'UNK-4',
|
||||
'Asia/Muscat': '<+04>-4',
|
||||
'Asia/Nicosia': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Asia/Novokuznetsk': 'UNK-7',
|
||||
'Asia/Novosibirsk': 'UNK-7',
|
||||
'Asia/Omsk': 'UNK-6',
|
||||
'Asia/Oral': 'UNK-5',
|
||||
'Asia/Phnom_Penh': 'UNK-7',
|
||||
'Asia/Novokuznetsk': '<+07>-7',
|
||||
'Asia/Novosibirsk': '<+07>-7',
|
||||
'Asia/Omsk': '<+06>-6',
|
||||
'Asia/Oral': '<+05>-5',
|
||||
'Asia/Phnom_Penh': '<+07>-7',
|
||||
'Asia/Pontianak': 'WIB-7',
|
||||
'Asia/Pyongyang': 'KST-9',
|
||||
'Asia/Qatar': 'UNK-3',
|
||||
'Asia/Qyzylorda': 'UNK-5',
|
||||
'Asia/Riyadh': 'UNK-3',
|
||||
'Asia/Sakhalin': 'UNK-11',
|
||||
'Asia/Samarkand': 'UNK-5',
|
||||
'Asia/Qatar': '<+03>-3',
|
||||
'Asia/Qyzylorda': '<+05>-5',
|
||||
'Asia/Riyadh': '<+03>-3',
|
||||
'Asia/Sakhalin': '<+11>-11',
|
||||
'Asia/Samarkand': '<+05>-5',
|
||||
'Asia/Seoul': 'KST-9',
|
||||
'Asia/Shanghai': 'CST-8',
|
||||
'Asia/Singapore': 'UNK-8',
|
||||
'Asia/Srednekolymsk': 'UNK-11',
|
||||
'Asia/Singapore': '<+08>-8',
|
||||
'Asia/Srednekolymsk': '<+11>-11',
|
||||
'Asia/Taipei': 'CST-8',
|
||||
'Asia/Tashkent': 'UNK-5',
|
||||
'Asia/Tbilisi': 'UNK-4',
|
||||
'Asia/Tehran': 'UNK-3:30UNK,J79/24,J263/24',
|
||||
'Asia/Thimphu': 'UNK-6',
|
||||
'Asia/Tashkent': '<+05>-5',
|
||||
'Asia/Tbilisi': '<+04>-4',
|
||||
'Asia/Tehran': '<+0330>-3:30',
|
||||
'Asia/Thimphu': '<+06>-6',
|
||||
'Asia/Tokyo': 'JST-9',
|
||||
'Asia/Tomsk': 'UNK-7',
|
||||
'Asia/Ulaanbaatar': 'UNK-8',
|
||||
'Asia/Urumqi': 'UNK-6',
|
||||
'Asia/Ust-Nera': 'UNK-10',
|
||||
'Asia/Vientiane': 'UNK-7',
|
||||
'Asia/Vladivostok': 'UNK-10',
|
||||
'Asia/Yakutsk': 'UNK-9',
|
||||
'Asia/Yangon': 'UNK-6:30',
|
||||
'Asia/Yekaterinburg': 'UNK-5',
|
||||
'Asia/Yerevan': 'UNK-4',
|
||||
'Atlantic/Azores': 'UNK1UNK,M3.5.0/0,M10.5.0/1',
|
||||
'Asia/Tomsk': '<+07>-7',
|
||||
'Asia/Ulaanbaatar': '<+08>-8',
|
||||
'Asia/Urumqi': '<+06>-6',
|
||||
'Asia/Ust-Nera': '<+10>-10',
|
||||
'Asia/Vientiane': '<+07>-7',
|
||||
'Asia/Vladivostok': '<+10>-10',
|
||||
'Asia/Yakutsk': '<+09>-9',
|
||||
'Asia/Yangon': '<+0630>-6:30',
|
||||
'Asia/Yekaterinburg': '<+05>-5',
|
||||
'Asia/Yerevan': '<+04>-4',
|
||||
'Atlantic/Azores': '<-01>1<+00>,M3.5.0/0,M10.5.0/1',
|
||||
'Atlantic/Bermuda': 'AST4ADT,M3.2.0,M11.1.0',
|
||||
'Atlantic/Canary': 'WET0WEST,M3.5.0/1,M10.5.0',
|
||||
'Atlantic/Cape_Verde': 'UNK1',
|
||||
'Atlantic/Cape_Verde': '<-01>1',
|
||||
'Atlantic/Faroe': 'WET0WEST,M3.5.0/1,M10.5.0',
|
||||
'Atlantic/Madeira': 'WET0WEST,M3.5.0/1,M10.5.0',
|
||||
'Atlantic/Reykjavik': 'GMT0',
|
||||
'Atlantic/South_Georgia': 'UNK2',
|
||||
'Atlantic/South_Georgia': '<-02>2',
|
||||
'Atlantic/St_Helena': 'GMT0',
|
||||
'Atlantic/Stanley': 'UNK3',
|
||||
'Atlantic/Stanley': '<-03>3',
|
||||
'Australia/Adelaide': 'ACST-9:30ACDT,M10.1.0,M4.1.0/3',
|
||||
'Australia/Brisbane': 'AEST-10',
|
||||
'Australia/Broken_Hill': 'ACST-9:30ACDT,M10.1.0,M4.1.0/3',
|
||||
'Australia/Currie': 'AEST-10AEDT,M10.1.0,M4.1.0/3',
|
||||
'Australia/Darwin': 'ACST-9:30',
|
||||
'Australia/Eucla': 'UNK-8:45',
|
||||
'Australia/Eucla': '<+0845>-8:45',
|
||||
'Australia/Hobart': 'AEST-10AEDT,M10.1.0,M4.1.0/3',
|
||||
'Australia/Lindeman': 'AEST-10',
|
||||
'Australia/Lord_Howe': 'UNK-10:30UNK-11,M10.1.0,M4.1.0',
|
||||
'Australia/Lord_Howe': '<+1030>-10:30<+11>-11,M10.1.0,M4.1.0',
|
||||
'Australia/Melbourne': 'AEST-10AEDT,M10.1.0,M4.1.0/3',
|
||||
'Australia/Perth': 'AWST-8',
|
||||
'Australia/Sydney': 'AEST-10AEDT,M10.1.0,M4.1.0/3',
|
||||
'Etc/GMT': 'GMT0',
|
||||
'Etc/GMT+0': 'GMT0',
|
||||
'Etc/GMT+1': 'UNK1',
|
||||
'Etc/GMT+10': 'UNK10',
|
||||
'Etc/GMT+11': 'UNK11',
|
||||
'Etc/GMT+12': 'UNK12',
|
||||
'Etc/GMT+2': 'UNK2',
|
||||
'Etc/GMT+3': 'UNK3',
|
||||
'Etc/GMT+4': 'UNK4',
|
||||
'Etc/GMT+5': 'UNK5',
|
||||
'Etc/GMT+6': 'UNK6',
|
||||
'Etc/GMT+7': 'UNK7',
|
||||
'Etc/GMT+8': 'UNK8',
|
||||
'Etc/GMT+9': 'UNK9',
|
||||
'Etc/GMT+1': '<-01>1',
|
||||
'Etc/GMT+10': '<-10>10',
|
||||
'Etc/GMT+11': '<-11>11',
|
||||
'Etc/GMT+12': '<-12>12',
|
||||
'Etc/GMT+2': '<-02>2',
|
||||
'Etc/GMT+3': '<-03>3',
|
||||
'Etc/GMT+4': '<-04>4',
|
||||
'Etc/GMT+5': '<-05>5',
|
||||
'Etc/GMT+6': '<-06>6',
|
||||
'Etc/GMT+7': '<-07>7',
|
||||
'Etc/GMT+8': '<-08>8',
|
||||
'Etc/GMT+9': '<-09>9',
|
||||
'Etc/GMT-0': 'GMT0',
|
||||
'Etc/GMT-1': 'UNK-1',
|
||||
'Etc/GMT-10': 'UNK-10',
|
||||
'Etc/GMT-11': 'UNK-11',
|
||||
'Etc/GMT-12': 'UNK-12',
|
||||
'Etc/GMT-13': 'UNK-13',
|
||||
'Etc/GMT-14': 'UNK-14',
|
||||
'Etc/GMT-2': 'UNK-2',
|
||||
'Etc/GMT-3': 'UNK-3',
|
||||
'Etc/GMT-4': 'UNK-4',
|
||||
'Etc/GMT-5': 'UNK-5',
|
||||
'Etc/GMT-6': 'UNK-6',
|
||||
'Etc/GMT-7': 'UNK-7',
|
||||
'Etc/GMT-8': 'UNK-8',
|
||||
'Etc/GMT-9': 'UNK-9',
|
||||
'Etc/GMT-1': '<+01>-1',
|
||||
'Etc/GMT-10': '<+10>-10',
|
||||
'Etc/GMT-11': '<+11>-11',
|
||||
'Etc/GMT-12': '<+12>-12',
|
||||
'Etc/GMT-13': '<+13>-13',
|
||||
'Etc/GMT-14': '<+14>-14',
|
||||
'Etc/GMT-2': '<+02>-2',
|
||||
'Etc/GMT-3': '<+03>-3',
|
||||
'Etc/GMT-4': '<+04>-4',
|
||||
'Etc/GMT-5': '<+05>-5',
|
||||
'Etc/GMT-6': '<+06>-6',
|
||||
'Etc/GMT-7': '<+07>-7',
|
||||
'Etc/GMT-8': '<+08>-8',
|
||||
'Etc/GMT-9': '<+09>-9',
|
||||
'Etc/GMT0': 'GMT0',
|
||||
'Etc/Greenwich': 'GMT0',
|
||||
'Etc/UCT': 'UTC0',
|
||||
@@ -354,7 +354,7 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'Etc/Zulu': 'UTC0',
|
||||
'Europe/Amsterdam': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Andorra': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Astrakhan': 'UNK-4',
|
||||
'Europe/Astrakhan': '<+04>-4',
|
||||
'Europe/Athens': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Belgrade': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Berlin': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
@@ -363,18 +363,18 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'Europe/Bucharest': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Budapest': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Busingen': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Chisinau': 'EET-2EEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Chisinau': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Copenhagen': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Dublin': 'IST-1GMT0,M10.5.0,M3.5.0/1',
|
||||
'Europe/Gibraltar': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Guernsey': 'GMT0BST,M3.5.0/1,M10.5.0',
|
||||
'Europe/Helsinki': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Isle_of_Man': 'GMT0BST,M3.5.0/1,M10.5.0',
|
||||
'Europe/Istanbul': 'UNK-3',
|
||||
'Europe/Istanbul': '<+03>-3',
|
||||
'Europe/Jersey': 'GMT0BST,M3.5.0/1,M10.5.0',
|
||||
'Europe/Kaliningrad': 'EET-2',
|
||||
'Europe/Kiev': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Kirov': 'UNK-3',
|
||||
'Europe/Kirov': 'MSK-3',
|
||||
'Europe/Lisbon': 'WET0WEST,M3.5.0/1,M10.5.0',
|
||||
'Europe/Ljubljana': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/London': 'GMT0BST,M3.5.0/1,M10.5.0',
|
||||
@@ -382,7 +382,7 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'Europe/Madrid': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Malta': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Mariehamn': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Minsk': 'UNK-3',
|
||||
'Europe/Minsk': '<+03>-3',
|
||||
'Europe/Monaco': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Moscow': 'MSK-3',
|
||||
'Europe/Oslo': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
@@ -391,83 +391,114 @@ export const TIME_ZONES: Record<string, string> = {
|
||||
'Europe/Prague': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Riga': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Rome': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Samara': 'UNK-4',
|
||||
'Europe/Samara': '<+04>-4',
|
||||
'Europe/San_Marino': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Sarajevo': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Saratov': 'UNK-4',
|
||||
'Europe/Saratov': '<+04>-4',
|
||||
'Europe/Simferopol': 'MSK-3',
|
||||
'Europe/Skopje': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Sofia': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Stockholm': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Tallinn': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Tirane': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Ulyanovsk': 'UNK-4',
|
||||
'Europe/Ulyanovsk': '<+04>-4',
|
||||
'Europe/Uzhgorod': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Vaduz': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Vatican': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Vienna': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Vilnius': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Volgograd': 'UNK-4',
|
||||
'Europe/Volgograd': 'MSK-3',
|
||||
'Europe/Warsaw': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Zagreb': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Europe/Zaporozhye': 'EET-2EEST,M3.5.0/3,M10.5.0/4',
|
||||
'Europe/Zurich': 'CET-1CEST,M3.5.0,M10.5.0/3',
|
||||
'Indian/Antananarivo': 'EAT-3',
|
||||
'Indian/Chagos': 'UNK-6',
|
||||
'Indian/Christmas': 'UNK-7',
|
||||
'Indian/Cocos': 'UNK-6:30',
|
||||
'Indian/Chagos': '<+06>-6',
|
||||
'Indian/Christmas': '<+07>-7',
|
||||
'Indian/Cocos': '<+0630>-6:30',
|
||||
'Indian/Comoro': 'EAT-3',
|
||||
'Indian/Kerguelen': 'UNK-5',
|
||||
'Indian/Mahe': 'UNK-4',
|
||||
'Indian/Maldives': 'UNK-5',
|
||||
'Indian/Mauritius': 'UNK-4',
|
||||
'Indian/Kerguelen': '<+05>-5',
|
||||
'Indian/Mahe': '<+04>-4',
|
||||
'Indian/Maldives': '<+05>-5',
|
||||
'Indian/Mauritius': '<+04>-4',
|
||||
'Indian/Mayotte': 'EAT-3',
|
||||
'Indian/Reunion': 'UNK-4',
|
||||
'Pacific/Apia': 'UNK-13UNK,M9.5.0/3,M4.1.0/4',
|
||||
'Indian/Reunion': '<+04>-4',
|
||||
'Pacific/Apia': '<+13>-13',
|
||||
'Pacific/Auckland': 'NZST-12NZDT,M9.5.0,M4.1.0/3',
|
||||
'Pacific/Bougainville': 'UNK-11',
|
||||
'Pacific/Chatham': 'UNK-12:45UNK,M9.5.0/2:45,M4.1.0/3:45',
|
||||
'Pacific/Chuuk': 'UNK-10',
|
||||
'Pacific/Easter': 'UNK6UNK,M9.1.6/22,M4.1.6/22',
|
||||
'Pacific/Efate': 'UNK-11',
|
||||
'Pacific/Enderbury': 'UNK-13',
|
||||
'Pacific/Fakaofo': 'UNK-13',
|
||||
'Pacific/Fiji': 'UNK-12UNK,M11.2.0,M1.2.3/99',
|
||||
'Pacific/Funafuti': 'UNK-12',
|
||||
'Pacific/Galapagos': 'UNK6',
|
||||
'Pacific/Gambier': 'UNK9',
|
||||
'Pacific/Guadalcanal': 'UNK-11',
|
||||
'Pacific/Bougainville': '<+11>-11',
|
||||
'Pacific/Chatham': '<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45',
|
||||
'Pacific/Chuuk': '<+10>-10',
|
||||
'Pacific/Easter': '<-06>6<-05>,M9.1.6/22,M4.1.6/22',
|
||||
'Pacific/Efate': '<+11>-11',
|
||||
'Pacific/Enderbury': '<+13>-13',
|
||||
'Pacific/Fakaofo': '<+13>-13',
|
||||
'Pacific/Fiji': '<+12>-12',
|
||||
'Pacific/Funafuti': '<+12>-12',
|
||||
'Pacific/Galapagos': '<-06>6',
|
||||
'Pacific/Gambier': '<-09>9',
|
||||
'Pacific/Guadalcanal': '<+11>-11',
|
||||
'Pacific/Guam': 'ChST-10',
|
||||
'Pacific/Honolulu': 'HST10',
|
||||
'Pacific/Kiritimati': 'UNK-14',
|
||||
'Pacific/Kosrae': 'UNK-11',
|
||||
'Pacific/Kwajalein': 'UNK-12',
|
||||
'Pacific/Majuro': 'UNK-12',
|
||||
'Pacific/Marquesas': 'UNK9:30',
|
||||
'Pacific/Kiritimati': '<+14>-14',
|
||||
'Pacific/Kosrae': '<+11>-11',
|
||||
'Pacific/Kwajalein': '<+12>-12',
|
||||
'Pacific/Majuro': '<+12>-12',
|
||||
'Pacific/Marquesas': '<-0930>9:30',
|
||||
'Pacific/Midway': 'SST11',
|
||||
'Pacific/Nauru': 'UNK-12',
|
||||
'Pacific/Niue': 'UNK11',
|
||||
'Pacific/Norfolk': 'UNK-11UNK,M10.1.0,M4.1.0/3',
|
||||
'Pacific/Noumea': 'UNK-11',
|
||||
'Pacific/Nauru': '<+12>-12',
|
||||
'Pacific/Niue': '<-11>11',
|
||||
'Pacific/Norfolk': '<+11>-11<+12>,M10.1.0,M4.1.0/3',
|
||||
'Pacific/Noumea': '<+11>-11',
|
||||
'Pacific/Pago_Pago': 'SST11',
|
||||
'Pacific/Palau': 'UNK-9',
|
||||
'Pacific/Pitcairn': 'UNK8',
|
||||
'Pacific/Pohnpei': 'UNK-11',
|
||||
'Pacific/Port_Moresby': 'UNK-10',
|
||||
'Pacific/Rarotonga': 'UNK10',
|
||||
'Pacific/Palau': '<+09>-9',
|
||||
'Pacific/Pitcairn': '<-08>8',
|
||||
'Pacific/Pohnpei': '<+11>-11',
|
||||
'Pacific/Port_Moresby': '<+10>-10',
|
||||
'Pacific/Rarotonga': '<-10>10',
|
||||
'Pacific/Saipan': 'ChST-10',
|
||||
'Pacific/Tahiti': 'UNK10',
|
||||
'Pacific/Tarawa': 'UNK-12',
|
||||
'Pacific/Tongatapu': 'UNK-13',
|
||||
'Pacific/Wake': 'UNK-12',
|
||||
'Pacific/Wallis': 'UNK-12'
|
||||
'Pacific/Tahiti': '<-10>10',
|
||||
'Pacific/Tarawa': '<+12>-12',
|
||||
'Pacific/Tongatapu': '<+13>-13',
|
||||
'Pacific/Wake': '<+12>-12',
|
||||
'Pacific/Wallis': '<+12>-12'
|
||||
};
|
||||
|
||||
// Pre-compute sorted timezone labels for better performance
|
||||
export const TIME_ZONE_LABELS = Object.keys(TIME_ZONES).sort();
|
||||
|
||||
/** Resolve the select value for a saved zone. Prefer the label when it is in
|
||||
* TIME_ZONES so a stale stored tz_format (after a table update) still shows the
|
||||
* correct city; firmware migrates the format from the label on boot. */
|
||||
export function selectedTimeZone(label: string, format: string) {
|
||||
return TIME_ZONES[label] === format ? label : undefined;
|
||||
if (label in TIME_ZONES) {
|
||||
return label;
|
||||
}
|
||||
return Object.keys(TIME_ZONES).find((key) => TIME_ZONES[key] === format);
|
||||
}
|
||||
|
||||
/** Return settings with tz_format / tz_format_t refreshed from TIME_ZONES, or
|
||||
* null if already current (or labels are unknown). */
|
||||
export function migrateNtpTimeZones<
|
||||
T extends {
|
||||
tz_label: string;
|
||||
tz_format: string;
|
||||
tz_label_t: string;
|
||||
tz_format_t: string;
|
||||
}
|
||||
>(settings: T): T | null {
|
||||
const tz_format = TIME_ZONES[settings.tz_label];
|
||||
const tz_format_t = TIME_ZONES[settings.tz_label_t];
|
||||
const next = { ...settings };
|
||||
let changed = false;
|
||||
if (tz_format && tz_format !== settings.tz_format) {
|
||||
next.tz_format = tz_format;
|
||||
changed = true;
|
||||
}
|
||||
if (tz_format_t && tz_format_t !== settings.tz_format_t) {
|
||||
next.tz_format_t = tz_format_t;
|
||||
changed = true;
|
||||
}
|
||||
return changed ? next : null;
|
||||
}
|
||||
|
||||
const precomputedTimeZoneItems = TIME_ZONE_LABELS.map((label) => (
|
||||
|
||||
@@ -13,7 +13,7 @@ using espMqttClientInternals::PacketType;
|
||||
using espMqttClientTypes::DisconnectReason;
|
||||
using espMqttClientTypes::Error;
|
||||
|
||||
MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority, uint8_t core)
|
||||
MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority, uint8_t core, uint32_t stackSize)
|
||||
: _useInternalTask(useInternalTask)
|
||||
, _transport(nullptr)
|
||||
, _onConnectCallback(nullptr)
|
||||
@@ -55,6 +55,7 @@ MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint
|
||||
, _disconnectReason(DisconnectReason::TCP_DISCONNECTED)
|
||||
#if defined(ARDUINO_ARCH_ESP32) && ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
|
||||
, _highWaterMark(4294967295)
|
||||
, _stackSize(stackSize)
|
||||
#endif
|
||||
{
|
||||
EMC_GENERATE_CLIENTID(_generatedClientId);
|
||||
@@ -64,12 +65,12 @@ MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint
|
||||
if (_useInternalTask == espMqttClientTypes::UseInternalTask::YES) {
|
||||
#ifdef CONFIG_FREERTOS_UNICORE
|
||||
// no core to pin to on single-core targets (S2, C3, C6)
|
||||
xTaskCreate((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle);
|
||||
xTaskCreate((TaskFunction_t)_loop, "mqttclient", stackSize, this, priority, &_taskHandle);
|
||||
#else
|
||||
if (core > 1) {
|
||||
xTaskCreate((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle);
|
||||
xTaskCreate((TaskFunction_t)_loop, "mqttclient", stackSize, this, priority, &_taskHandle);
|
||||
} else {
|
||||
xTaskCreatePinnedToCore((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle, core);
|
||||
xTaskCreatePinnedToCore((TaskFunction_t)_loop, "mqttclient", stackSize, this, priority, &_taskHandle, core);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -77,6 +78,7 @@ MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint
|
||||
(void) useInternalTask;
|
||||
(void) priority;
|
||||
(void) core;
|
||||
(void) stackSize;
|
||||
#endif
|
||||
_clientId = _generatedClientId;
|
||||
_core = core;
|
||||
@@ -320,7 +322,7 @@ void MqttClient::loop() {
|
||||
size_t waterMark = uxTaskGetStackHighWaterMark(NULL);
|
||||
if (waterMark < _highWaterMark) {
|
||||
_highWaterMark = waterMark;
|
||||
emc_log_i("Stack usage: %zu/%i", EMC_TASK_STACK_SIZE - _highWaterMark, EMC_TASK_STACK_SIZE);
|
||||
emc_log_i("Stack usage: %zu/%zu", _stackSize - _highWaterMark, _stackSize);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ class MqttClient {
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority = 1, uint8_t core = 1);
|
||||
explicit MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority = 1, uint8_t core = 1, uint32_t stackSize = EMC_TASK_STACK_SIZE);
|
||||
espMqttClientTypes::UseInternalTask _useInternalTask;
|
||||
espMqttClientInternals::Transport* _transport;
|
||||
|
||||
@@ -207,6 +207,7 @@ class MqttClient {
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#if ARDUHAL_LOG_LEVEL >= ARDUHAL_LOG_LEVEL_INFO
|
||||
size_t _highWaterMark;
|
||||
size_t _stackSize;
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -208,8 +208,8 @@ class MqttClientSetup : public MqttClient {
|
||||
*/
|
||||
|
||||
protected:
|
||||
explicit MqttClientSetup(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority = 1, uint8_t core = 1)
|
||||
: MqttClient(useInternalTask, priority, core) {
|
||||
explicit MqttClientSetup(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority = 1, uint8_t core = 1, uint32_t stackSize = EMC_TASK_STACK_SIZE)
|
||||
: MqttClient(useInternalTask, priority, core, stackSize) {
|
||||
#if EMC_MULTIPLE_CALLBACKS
|
||||
_onConnectCallback = [this](bool sessionPresent) {
|
||||
for (auto callback : _onConnectCallbacks) if (callback.first) callback.first(sessionPresent);
|
||||
|
||||
@@ -15,8 +15,8 @@ espMqttClient::espMqttClient(espMqttClientTypes::UseInternalTask useInternalTask
|
||||
_transport = &_client;
|
||||
}
|
||||
|
||||
espMqttClient::espMqttClient(uint8_t priority, uint8_t core)
|
||||
: MqttClientSetup(espMqttClientTypes::UseInternalTask::YES, priority, core)
|
||||
espMqttClient::espMqttClient(uint8_t priority, uint8_t core, uint32_t stackSize)
|
||||
: MqttClientSetup(espMqttClientTypes::UseInternalTask::YES, priority, core, stackSize)
|
||||
, _client() {
|
||||
_transport = &_client;
|
||||
}
|
||||
@@ -27,8 +27,8 @@ espMqttClientSecure::espMqttClientSecure(espMqttClientTypes::UseInternalTask use
|
||||
_transport = &_client;
|
||||
}
|
||||
|
||||
espMqttClientSecure::espMqttClientSecure(uint8_t priority, uint8_t core)
|
||||
: MqttClientSetup(espMqttClientTypes::UseInternalTask::YES, priority, core)
|
||||
espMqttClientSecure::espMqttClientSecure(uint8_t priority, uint8_t core, uint32_t stackSize)
|
||||
: MqttClientSetup(espMqttClientTypes::UseInternalTask::YES, priority, core, stackSize)
|
||||
, _client() {
|
||||
_transport = &_client;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class espMqttClientSecure : public MqttClientSetup<espMqttClientSecure> {
|
||||
class espMqttClient : public MqttClientSetup<espMqttClient> {
|
||||
public:
|
||||
explicit espMqttClient(espMqttClientTypes::UseInternalTask useInternalTask);
|
||||
explicit espMqttClient(uint8_t priority = 1, uint8_t core = 1);
|
||||
explicit espMqttClient(uint8_t priority = 1, uint8_t core = 1, uint32_t stackSize = EMC_TASK_STACK_SIZE);
|
||||
|
||||
protected:
|
||||
espMqttClientInternals::ClientSync _client;
|
||||
@@ -57,7 +57,7 @@ class espMqttClient : public MqttClientSetup<espMqttClient> {
|
||||
class espMqttClientSecure : public MqttClientSetup<espMqttClientSecure> {
|
||||
public:
|
||||
explicit espMqttClientSecure(espMqttClientTypes::UseInternalTask useInternalTask);
|
||||
explicit espMqttClientSecure(uint8_t priority = 1, uint8_t core = 1);
|
||||
explicit espMqttClientSecure(uint8_t priority = 1, uint8_t core = 1, uint32_t stackSize = EMC_TASK_STACK_SIZE);
|
||||
espMqttClientSecure & setInsecure();
|
||||
espMqttClientSecure & setCACert(const char * rootCA);
|
||||
espMqttClientSecure & setCertificate(const char * clientCa);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate src/ESP32React/tz_zones.h from interface/src/app/settings/TZ.tsx.
|
||||
|
||||
Run from the repo root:
|
||||
python3 scripts/generate_tz_zones.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
TZ_TSX = ROOT / "interface" / "src" / "app" / "settings" / "TZ.tsx"
|
||||
OUT_H = ROOT / "src" / "ESP32React" / "tz_zones.h"
|
||||
|
||||
|
||||
def parse_time_zones(text: str) -> list[tuple[str, str]]:
|
||||
match = re.search(
|
||||
r"export const TIME_ZONES: Record<string, string> = \{([\s\S]*?)\n\};",
|
||||
text,
|
||||
)
|
||||
if not match:
|
||||
raise SystemExit("TIME_ZONES table not found in TZ.tsx")
|
||||
entries = re.findall(r"'((?:\\'|[^'])*)': '((?:\\'|[^'])*)'", match.group(1))
|
||||
if not entries:
|
||||
raise SystemExit("no TIME_ZONES entries parsed")
|
||||
return sorted(entries, key=lambda item: item[0])
|
||||
|
||||
|
||||
def c_string(value: str) -> str:
|
||||
return '"' + value.replace("\\", "\\\\").replace('"', '\\"') + '"'
|
||||
|
||||
|
||||
def main() -> int:
|
||||
entries = parse_time_zones(TZ_TSX.read_text(encoding="utf-8"))
|
||||
max_format = max(len(fmt) for _, fmt in entries)
|
||||
|
||||
lines = [
|
||||
"/* Auto-generated by scripts/generate_tz_zones.py — do not edit. */",
|
||||
"#pragma once",
|
||||
"",
|
||||
"#include <stdlib.h>",
|
||||
"#include <string.h>",
|
||||
"",
|
||||
"struct EmsespTzZone {",
|
||||
" const char * label;",
|
||||
" const char * format;",
|
||||
"};",
|
||||
"",
|
||||
f"// Longest POSIX TZ value in the table is {max_format} chars.",
|
||||
"static constexpr size_t EMSESP_TZ_ZONE_COUNT = "
|
||||
f"{len(entries)};",
|
||||
"static const EmsespTzZone EMSESP_TZ_ZONES[EMSESP_TZ_ZONE_COUNT] = {",
|
||||
]
|
||||
for label, fmt in entries:
|
||||
lines.append(f" {{{c_string(label)}, {c_string(fmt)}}},")
|
||||
lines += [
|
||||
"};",
|
||||
"",
|
||||
"inline int emsesp_tz_zone_cmp(const void * key, const void * element) {",
|
||||
" return strcmp(static_cast<const char *>(key), static_cast<const EmsespTzZone *>(element)->label);",
|
||||
"}",
|
||||
"",
|
||||
"// Returns the POSIX TZ string for an IANA label, or nullptr if unknown.",
|
||||
"inline const char * emsesp_tz_format_for_label(const char * label) {",
|
||||
" if (label == nullptr || *label == '\\0') {",
|
||||
" return nullptr;",
|
||||
" }",
|
||||
" const auto * found = static_cast<const EmsespTzZone *>(",
|
||||
" bsearch(label, EMSESP_TZ_ZONES, EMSESP_TZ_ZONE_COUNT, sizeof(EmsespTzZone), emsesp_tz_zone_cmp));",
|
||||
" return found != nullptr ? found->format : nullptr;",
|
||||
"}",
|
||||
"",
|
||||
]
|
||||
OUT_H.write_text("\n".join(lines), encoding="utf-8")
|
||||
print(f"Wrote {OUT_H.relative_to(ROOT)} ({len(entries)} zones, max format {max_format})")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -32,10 +32,13 @@ void MqttSettingsService::begin() {
|
||||
}
|
||||
|
||||
void MqttSettingsService::startClient() {
|
||||
static bool isSecure = false;
|
||||
static bool isSecure = false;
|
||||
static uint32_t stackSize = EMC_TASK_STACK_SIZE;
|
||||
// only verifying a CA chain needs the larger stack, insecure TLS and plain MQTT fit in the default
|
||||
const uint32_t wantStack = (_state.enableTLS && _state.rootCA != "insecure") ? EMSESP_MQTT_STACKSIZE_CA : EMC_TASK_STACK_SIZE;
|
||||
if (_mqttClient) {
|
||||
// do we need to change the client?
|
||||
if ((isSecure && _state.enableTLS) || (!isSecure && !_state.enableTLS)) {
|
||||
if (isSecure == _state.enableTLS && stackSize == wantStack) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -43,12 +46,14 @@ void MqttSettingsService::startClient() {
|
||||
_mqttClient = nullptr;
|
||||
}
|
||||
|
||||
stackSize = wantStack;
|
||||
|
||||
if (_state.enableTLS) {
|
||||
isSecure = true;
|
||||
if (emsesp::EMSESP::system_.PSram() == 0) {
|
||||
_mqttClient = new espMqttClientSecure(espMqttClientTypes::UseInternalTask::NO);
|
||||
} else {
|
||||
_mqttClient = new espMqttClientSecure(EMSESP_MQTT_PRIORITY, EMSESP_MQTT_RUNNING_CORE);
|
||||
_mqttClient = new espMqttClientSecure(EMSESP_MQTT_PRIORITY, EMSESP_MQTT_RUNNING_CORE, wantStack);
|
||||
}
|
||||
|
||||
if (!_mqttClient) {
|
||||
|
||||
@@ -60,6 +60,11 @@
|
||||
#define EMC_TASK_STACK_SIZE EMSESP_MQTT_STACKSIZE
|
||||
#endif
|
||||
|
||||
// MQTT task stack when TLS verifies the broker against a CA. BearSSL needs ~6 KB to verify an EC (P-384, P-521) chain
|
||||
#ifndef EMSESP_MQTT_STACKSIZE_CA
|
||||
#define EMSESP_MQTT_STACKSIZE_CA 8192
|
||||
#endif
|
||||
|
||||
#ifndef EMSESP_MQTT_PRIORITY
|
||||
#define EMSESP_MQTT_PRIORITY 1
|
||||
#endif
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
#include "NTPSettingsService.h"
|
||||
|
||||
#include "tz_zones.h"
|
||||
|
||||
#include <emsesp.h>
|
||||
|
||||
namespace {
|
||||
|
||||
String trimmedTzFormat(const String & format) {
|
||||
int space = format.indexOf(' ');
|
||||
return space < 0 ? format : format.substring(0, static_cast<unsigned int>(space));
|
||||
}
|
||||
|
||||
void padTzFormat(String & format) {
|
||||
format.reserve(NTP_TZ_FORMAT_LEN);
|
||||
while (format.length() < NTP_TZ_FORMAT_LEN) {
|
||||
format += ' ';
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NTPSettingsService::NTPSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||
: _httpEndpoint(NTPSettings::read, NTPSettings::update, this, server, NTP_SETTINGS_SERVICE_PATH, securityManager)
|
||||
, _fsPersistence(NTPSettings::read, NTPSettings::update, this, fs, NTP_SETTINGS_FILE)
|
||||
@@ -16,6 +34,13 @@ NTPSettingsService::NTPSettingsService(AsyncWebServer * server, FS * fs, Securit
|
||||
|
||||
void NTPSettingsService::begin() {
|
||||
_fsPersistence.readFromFS();
|
||||
|
||||
// After an OTA that updates tz_zones.h, rewrite stored POSIX strings from the
|
||||
// saved IANA labels so localtime / thermostat sync use the current rules
|
||||
// without the user re-selecting the zone in the WebUI.
|
||||
update([](NTPSettings & settings) {
|
||||
return NTPSettings::syncFormatsFromLabels(settings) ? StateUpdateResult::CHANGED : StateUpdateResult::UNCHANGED;
|
||||
});
|
||||
}
|
||||
|
||||
void NTPSettingsService::loop() {
|
||||
@@ -77,15 +102,40 @@ void NTPSettings::read(NTPSettings & settings, JsonObject root) {
|
||||
root["enabled"] = settings.enabled;
|
||||
root["server"] = settings.server;
|
||||
root["tz_label"] = settings.tzLabel;
|
||||
root["tz_format"] = settings.tzFormat.substring(0, settings.tzFormat.indexOf(" "));
|
||||
root["tz_format"] = trimmedTzFormat(settings.tzFormat);
|
||||
root["thermostat_sync"] = settings.thermostat_sync;
|
||||
root["tz_label_t"] = settings.tzLabelT;
|
||||
root["tz_format_t"] = settings.tzFormatT.substring(0, settings.tzFormatT.indexOf(" "));
|
||||
root["tz_format_t"] = trimmedTzFormat(settings.tzFormatT);
|
||||
}
|
||||
|
||||
bool NTPSettings::syncFormatsFromLabels(NTPSettings & settings) {
|
||||
bool changed = false;
|
||||
|
||||
auto apply = [&](const String & label, String & format) {
|
||||
const char * mapped = emsesp_tz_format_for_label(label.c_str());
|
||||
if (mapped == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (trimmedTzFormat(format) == mapped) {
|
||||
// Still re-pad in case NTP_TZ_FORMAT_LEN grew since the value was stored.
|
||||
if (format.length() != NTP_TZ_FORMAT_LEN) {
|
||||
format = mapped;
|
||||
padTzFormat(format);
|
||||
changed = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
format = mapped;
|
||||
padTzFormat(format);
|
||||
changed = true;
|
||||
};
|
||||
|
||||
apply(settings.tzLabel, settings.tzFormat);
|
||||
apply(settings.tzLabelT, settings.tzFormatT);
|
||||
return changed;
|
||||
}
|
||||
|
||||
StateUpdateResult NTPSettings::update(JsonObject root, NTPSettings & settings) {
|
||||
settings.tzFormat.reserve(40);
|
||||
settings.tzFormatT.reserve(40);
|
||||
settings.enabled = root["enabled"] | FACTORY_NTP_ENABLED;
|
||||
settings.server = root["server"] | FACTORY_NTP_SERVER;
|
||||
settings.tzLabel = root["tz_label"] | FACTORY_NTP_TIME_ZONE_LABEL;
|
||||
@@ -93,14 +143,15 @@ StateUpdateResult NTPSettings::update(JsonObject root, NTPSettings & settings) {
|
||||
settings.thermostat_sync = root["thermostat_sync"] | FACTORY_NTP_THERMOSTAT_SYNC;
|
||||
settings.tzLabelT = root["tz_label_t"] | FACTORY_NTP_TIME_ZONE_LABEL;
|
||||
settings.tzFormatT = root["tz_format_t"] | FACTORY_NTP_TIME_ZONE_FORMAT;
|
||||
// The format string must have same length to avoid memory leak, #3184
|
||||
while (settings.tzFormat.length() < 40) {
|
||||
settings.tzFormat += " ";
|
||||
}
|
||||
|
||||
while (settings.tzFormatT.length() < 40) {
|
||||
settings.tzFormatT += " ";
|
||||
}
|
||||
// Do not call syncFormatsFromLabels here: readFromFS() uses this updater
|
||||
// via updateWithoutPropagation, and a sync at that point would not be
|
||||
// written back. Boot migration runs in NTPSettingsService::begin() instead.
|
||||
// The WebUI always POSTs tz_format from TIME_ZONES when the user saves.
|
||||
|
||||
// The format string must have a fixed length to avoid a setenv leak, #3184.
|
||||
padTzFormat(settings.tzFormat);
|
||||
padTzFormat(settings.tzFormatT);
|
||||
|
||||
return StateUpdateResult::CHANGED;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,12 @@
|
||||
#define NTP_SETTINGS_SERVICE_PATH "/rest/ntpSettings"
|
||||
#define TIME_PATH "/rest/time"
|
||||
|
||||
// Fixed length for tz_format passed to setenv to avoid the realloc leak in #3184.
|
||||
// Must be >= longest POSIX TZ string in tz_zones.h (currently 44 for Pacific/Chatham).
|
||||
#ifndef NTP_TZ_FORMAT_LEN
|
||||
#define NTP_TZ_FORMAT_LEN 48
|
||||
#endif
|
||||
|
||||
class NTPSettings {
|
||||
public:
|
||||
bool enabled = FACTORY_NTP_ENABLED;
|
||||
@@ -44,6 +50,10 @@ class NTPSettings {
|
||||
|
||||
static void read(NTPSettings & settings, JsonObject root);
|
||||
static StateUpdateResult update(JsonObject root, NTPSettings & settings);
|
||||
|
||||
// Refresh tz_format / tz_format_t from the IANA label using tz_zones.h.
|
||||
// Returns true if either format string changed.
|
||||
static bool syncFormatsFromLabels(NTPSettings & settings);
|
||||
};
|
||||
|
||||
class NTPSettingsService : public StatefulService<NTPSettings> {
|
||||
|
||||
@@ -0,0 +1,489 @@
|
||||
/* Auto-generated by scripts/generate_tz_zones.py — do not edit. */
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct EmsespTzZone {
|
||||
const char * label;
|
||||
const char * format;
|
||||
};
|
||||
|
||||
// Longest POSIX TZ value in the table is 44 chars.
|
||||
static constexpr size_t EMSESP_TZ_ZONE_COUNT = 460;
|
||||
static const EmsespTzZone EMSESP_TZ_ZONES[EMSESP_TZ_ZONE_COUNT] = {
|
||||
{"Africa/Abidjan", "GMT0"},
|
||||
{"Africa/Accra", "GMT0"},
|
||||
{"Africa/Addis_Ababa", "EAT-3"},
|
||||
{"Africa/Algiers", "CET-1"},
|
||||
{"Africa/Asmara", "EAT-3"},
|
||||
{"Africa/Bamako", "GMT0"},
|
||||
{"Africa/Bangui", "WAT-1"},
|
||||
{"Africa/Banjul", "GMT0"},
|
||||
{"Africa/Bissau", "GMT0"},
|
||||
{"Africa/Blantyre", "CAT-2"},
|
||||
{"Africa/Brazzaville", "WAT-1"},
|
||||
{"Africa/Bujumbura", "CAT-2"},
|
||||
{"Africa/Cairo", "EET-2EEST,M4.5.5/0,M10.5.4/24"},
|
||||
{"Africa/Casablanca", "<+00>0"},
|
||||
{"Africa/Ceuta", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Africa/Conakry", "GMT0"},
|
||||
{"Africa/Dakar", "GMT0"},
|
||||
{"Africa/Dar_es_Salaam", "EAT-3"},
|
||||
{"Africa/Djibouti", "EAT-3"},
|
||||
{"Africa/Douala", "WAT-1"},
|
||||
{"Africa/El_Aaiun", "<+00>0"},
|
||||
{"Africa/Freetown", "GMT0"},
|
||||
{"Africa/Gaborone", "CAT-2"},
|
||||
{"Africa/Harare", "CAT-2"},
|
||||
{"Africa/Johannesburg", "SAST-2"},
|
||||
{"Africa/Juba", "CAT-2"},
|
||||
{"Africa/Kampala", "EAT-3"},
|
||||
{"Africa/Khartoum", "CAT-2"},
|
||||
{"Africa/Kigali", "CAT-2"},
|
||||
{"Africa/Kinshasa", "WAT-1"},
|
||||
{"Africa/Lagos", "WAT-1"},
|
||||
{"Africa/Libreville", "WAT-1"},
|
||||
{"Africa/Lome", "GMT0"},
|
||||
{"Africa/Luanda", "WAT-1"},
|
||||
{"Africa/Lubumbashi", "CAT-2"},
|
||||
{"Africa/Lusaka", "CAT-2"},
|
||||
{"Africa/Malabo", "WAT-1"},
|
||||
{"Africa/Maputo", "CAT-2"},
|
||||
{"Africa/Maseru", "SAST-2"},
|
||||
{"Africa/Mbabane", "SAST-2"},
|
||||
{"Africa/Mogadishu", "EAT-3"},
|
||||
{"Africa/Monrovia", "GMT0"},
|
||||
{"Africa/Nairobi", "EAT-3"},
|
||||
{"Africa/Ndjamena", "WAT-1"},
|
||||
{"Africa/Niamey", "WAT-1"},
|
||||
{"Africa/Nouakchott", "GMT0"},
|
||||
{"Africa/Ouagadougou", "GMT0"},
|
||||
{"Africa/Porto-Novo", "WAT-1"},
|
||||
{"Africa/Sao_Tome", "GMT0"},
|
||||
{"Africa/Tripoli", "EET-2"},
|
||||
{"Africa/Tunis", "CET-1"},
|
||||
{"Africa/Windhoek", "CAT-2"},
|
||||
{"America/Adak", "HST10HDT,M3.2.0,M11.1.0"},
|
||||
{"America/Anchorage", "AKST9AKDT,M3.2.0,M11.1.0"},
|
||||
{"America/Anguilla", "AST4"},
|
||||
{"America/Antigua", "AST4"},
|
||||
{"America/Araguaina", "<-03>3"},
|
||||
{"America/Argentina/Buenos_Aires", "<-03>3"},
|
||||
{"America/Argentina/Catamarca", "<-03>3"},
|
||||
{"America/Argentina/Cordoba", "<-03>3"},
|
||||
{"America/Argentina/Jujuy", "<-03>3"},
|
||||
{"America/Argentina/La_Rioja", "<-03>3"},
|
||||
{"America/Argentina/Mendoza", "<-03>3"},
|
||||
{"America/Argentina/Rio_Gallegos", "<-03>3"},
|
||||
{"America/Argentina/Salta", "<-03>3"},
|
||||
{"America/Argentina/San_Juan", "<-03>3"},
|
||||
{"America/Argentina/San_Luis", "<-03>3"},
|
||||
{"America/Argentina/Tucuman", "<-03>3"},
|
||||
{"America/Argentina/Ushuaia", "<-03>3"},
|
||||
{"America/Aruba", "AST4"},
|
||||
{"America/Asuncion", "<-03>3"},
|
||||
{"America/Atikokan", "EST5"},
|
||||
{"America/Bahia", "<-03>3"},
|
||||
{"America/Bahia_Banderas", "CST6"},
|
||||
{"America/Barbados", "AST4"},
|
||||
{"America/Belem", "<-03>3"},
|
||||
{"America/Belize", "CST6"},
|
||||
{"America/Blanc-Sablon", "AST4"},
|
||||
{"America/Boa_Vista", "<-04>4"},
|
||||
{"America/Bogota", "<-05>5"},
|
||||
{"America/Boise", "MST7MDT,M3.2.0,M11.1.0"},
|
||||
{"America/Cambridge_Bay", "MST7MDT,M3.2.0,M11.1.0"},
|
||||
{"America/Campo_Grande", "<-04>4"},
|
||||
{"America/Cancun", "EST5"},
|
||||
{"America/Caracas", "<-04>4"},
|
||||
{"America/Cayenne", "<-03>3"},
|
||||
{"America/Cayman", "EST5"},
|
||||
{"America/Chicago", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Chihuahua", "CST6"},
|
||||
{"America/Costa_Rica", "CST6"},
|
||||
{"America/Creston", "MST7"},
|
||||
{"America/Cuiaba", "<-04>4"},
|
||||
{"America/Curacao", "AST4"},
|
||||
{"America/Danmarkshavn", "GMT0"},
|
||||
{"America/Dawson", "MST7"},
|
||||
{"America/Dawson_Creek", "MST7"},
|
||||
{"America/Denver", "MST7MDT,M3.2.0,M11.1.0"},
|
||||
{"America/Detroit", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Dominica", "AST4"},
|
||||
{"America/Edmonton", "CST6"},
|
||||
{"America/Eirunepe", "<-05>5"},
|
||||
{"America/El_Salvador", "CST6"},
|
||||
{"America/Fort_Nelson", "MST7"},
|
||||
{"America/Fortaleza", "<-03>3"},
|
||||
{"America/Glace_Bay", "AST4ADT,M3.2.0,M11.1.0"},
|
||||
{"America/Godthab", "<-02>2<-01>,M3.5.0/-1,M10.5.0/0"},
|
||||
{"America/Goose_Bay", "AST4ADT,M3.2.0,M11.1.0"},
|
||||
{"America/Grand_Turk", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Grenada", "AST4"},
|
||||
{"America/Guadeloupe", "AST4"},
|
||||
{"America/Guatemala", "CST6"},
|
||||
{"America/Guayaquil", "<-05>5"},
|
||||
{"America/Guyana", "<-04>4"},
|
||||
{"America/Halifax", "AST4ADT,M3.2.0,M11.1.0"},
|
||||
{"America/Havana", "CST5CDT,M3.2.0/0,M11.1.0/1"},
|
||||
{"America/Hermosillo", "MST7"},
|
||||
{"America/Indiana/Indianapolis", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Indiana/Knox", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Indiana/Marengo", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Indiana/Petersburg", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Indiana/Tell_City", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Indiana/Vevay", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Indiana/Vincennes", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Indiana/Winamac", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Inuvik", "CST6"},
|
||||
{"America/Iqaluit", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Jamaica", "EST5"},
|
||||
{"America/Juneau", "AKST9AKDT,M3.2.0,M11.1.0"},
|
||||
{"America/Kentucky/Louisville", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Kentucky/Monticello", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Kralendijk", "AST4"},
|
||||
{"America/La_Paz", "<-04>4"},
|
||||
{"America/Lima", "<-05>5"},
|
||||
{"America/Los_Angeles", "PST8PDT,M3.2.0,M11.1.0"},
|
||||
{"America/Lower_Princes", "AST4"},
|
||||
{"America/Maceio", "<-03>3"},
|
||||
{"America/Managua", "CST6"},
|
||||
{"America/Manaus", "<-04>4"},
|
||||
{"America/Marigot", "AST4"},
|
||||
{"America/Martinique", "AST4"},
|
||||
{"America/Matamoros", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Mazatlan", "MST7"},
|
||||
{"America/Menominee", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Merida", "CST6"},
|
||||
{"America/Metlakatla", "AKST9AKDT,M3.2.0,M11.1.0"},
|
||||
{"America/Mexico_City", "CST6"},
|
||||
{"America/Miquelon", "<-03>3<-02>,M3.2.0,M11.1.0"},
|
||||
{"America/Moncton", "AST4ADT,M3.2.0,M11.1.0"},
|
||||
{"America/Monterrey", "CST6"},
|
||||
{"America/Montevideo", "<-03>3"},
|
||||
{"America/Montreal", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Montserrat", "AST4"},
|
||||
{"America/Nassau", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/New_York", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Nipigon", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Nome", "AKST9AKDT,M3.2.0,M11.1.0"},
|
||||
{"America/Noronha", "<-02>2"},
|
||||
{"America/North_Dakota/Beulah", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/North_Dakota/Center", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/North_Dakota/New_Salem", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Ojinaga", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Panama", "EST5"},
|
||||
{"America/Pangnirtung", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Paramaribo", "<-03>3"},
|
||||
{"America/Phoenix", "MST7"},
|
||||
{"America/Port-au-Prince", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Port_of_Spain", "AST4"},
|
||||
{"America/Porto_Velho", "<-04>4"},
|
||||
{"America/Puerto_Rico", "AST4"},
|
||||
{"America/Punta_Arenas", "<-03>3"},
|
||||
{"America/Rainy_River", "EST5"},
|
||||
{"America/Rankin_Inlet", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Recife", "<-03>3"},
|
||||
{"America/Regina", "CST6"},
|
||||
{"America/Resolute", "CST6CDT,M3.2.0,M11.1.0"},
|
||||
{"America/Rio_Branco", "<-05>5"},
|
||||
{"America/Santarem", "<-03>3"},
|
||||
{"America/Santiago", "<-04>4<-03>,M9.1.6/24,M4.1.6/24"},
|
||||
{"America/Santo_Domingo", "AST4"},
|
||||
{"America/Sao_Paulo", "<-03>3"},
|
||||
{"America/Scoresbysund", "<-02>2<-01>,M3.5.0/-1,M10.5.0/0"},
|
||||
{"America/Sitka", "AKST9AKDT,M3.2.0,M11.1.0"},
|
||||
{"America/St_Barthelemy", "AST4"},
|
||||
{"America/St_Johns", "NST3:30NDT,M3.2.0,M11.1.0"},
|
||||
{"America/St_Kitts", "AST4"},
|
||||
{"America/St_Lucia", "AST4"},
|
||||
{"America/St_Thomas", "AST4"},
|
||||
{"America/St_Vincent", "AST4"},
|
||||
{"America/Swift_Current", "CST6"},
|
||||
{"America/Tegucigalpa", "CST6"},
|
||||
{"America/Thule", "AST4ADT,M3.2.0,M11.1.0"},
|
||||
{"America/Thunder_Bay", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Tijuana", "PST8PDT,M3.2.0,M11.1.0"},
|
||||
{"America/Toronto", "EST5EDT,M3.2.0,M11.1.0"},
|
||||
{"America/Tortola", "AST4"},
|
||||
{"America/Vancouver", "MST7"},
|
||||
{"America/Whitehorse", "MST7"},
|
||||
{"America/Winnipeg", "EST5"},
|
||||
{"America/Yakutat", "AKST9AKDT,M3.2.0,M11.1.0"},
|
||||
{"America/Yellowknife", "CST6"},
|
||||
{"Antarctica/Casey", "<+08>-8"},
|
||||
{"Antarctica/Davis", "<+07>-7"},
|
||||
{"Antarctica/DumontDUrville", "<+10>-10"},
|
||||
{"Antarctica/Macquarie", "AEST-10AEDT,M10.1.0,M4.1.0/3"},
|
||||
{"Antarctica/Mawson", "<+05>-5"},
|
||||
{"Antarctica/McMurdo", "NZST-12NZDT,M9.5.0,M4.1.0/3"},
|
||||
{"Antarctica/Palmer", "<-03>3"},
|
||||
{"Antarctica/Rothera", "<-03>3"},
|
||||
{"Antarctica/Syowa", "<+03>-3"},
|
||||
{"Antarctica/Troll", "<+00>0<+02>-2,M3.5.0/1,M10.5.0/3"},
|
||||
{"Antarctica/Vostok", "<+05>-5"},
|
||||
{"Arctic/Longyearbyen", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Asia/Aden", "<+03>-3"},
|
||||
{"Asia/Almaty", "<+05>-5"},
|
||||
{"Asia/Amman", "<+03>-3"},
|
||||
{"Asia/Anadyr", "<+12>-12"},
|
||||
{"Asia/Aqtau", "<+05>-5"},
|
||||
{"Asia/Aqtobe", "<+05>-5"},
|
||||
{"Asia/Ashgabat", "<+05>-5"},
|
||||
{"Asia/Atyrau", "<+05>-5"},
|
||||
{"Asia/Baghdad", "<+03>-3"},
|
||||
{"Asia/Bahrain", "<+03>-3"},
|
||||
{"Asia/Baku", "<+04>-4"},
|
||||
{"Asia/Bangkok", "<+07>-7"},
|
||||
{"Asia/Barnaul", "<+07>-7"},
|
||||
{"Asia/Beirut", "EET-2EEST,M3.5.0/0,M10.5.0/0"},
|
||||
{"Asia/Bishkek", "<+06>-6"},
|
||||
{"Asia/Brunei", "<+08>-8"},
|
||||
{"Asia/Chita", "<+09>-9"},
|
||||
{"Asia/Choibalsan", "<+08>-8"},
|
||||
{"Asia/Colombo", "<+0530>-5:30"},
|
||||
{"Asia/Damascus", "<+03>-3"},
|
||||
{"Asia/Dhaka", "<+06>-6"},
|
||||
{"Asia/Dili", "<+09>-9"},
|
||||
{"Asia/Dubai", "<+04>-4"},
|
||||
{"Asia/Dushanbe", "<+05>-5"},
|
||||
{"Asia/Famagusta", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Asia/Gaza", "EET-2EEST,M3.4.4/50,M10.4.4/50"},
|
||||
{"Asia/Hebron", "EET-2EEST,M3.4.4/50,M10.4.4/50"},
|
||||
{"Asia/Ho_Chi_Minh", "<+07>-7"},
|
||||
{"Asia/Hong_Kong", "HKT-8"},
|
||||
{"Asia/Hovd", "<+07>-7"},
|
||||
{"Asia/Irkutsk", "<+08>-8"},
|
||||
{"Asia/Jakarta", "WIB-7"},
|
||||
{"Asia/Jayapura", "WIT-9"},
|
||||
{"Asia/Jerusalem", "IST-2IDT,M3.4.4/26,M10.5.0"},
|
||||
{"Asia/Kabul", "<+0430>-4:30"},
|
||||
{"Asia/Kamchatka", "<+12>-12"},
|
||||
{"Asia/Karachi", "PKT-5"},
|
||||
{"Asia/Kathmandu", "<+0545>-5:45"},
|
||||
{"Asia/Khandyga", "<+09>-9"},
|
||||
{"Asia/Kolkata", "IST-5:30"},
|
||||
{"Asia/Krasnoyarsk", "<+07>-7"},
|
||||
{"Asia/Kuala_Lumpur", "<+08>-8"},
|
||||
{"Asia/Kuching", "<+08>-8"},
|
||||
{"Asia/Kuwait", "<+03>-3"},
|
||||
{"Asia/Macau", "CST-8"},
|
||||
{"Asia/Magadan", "<+11>-11"},
|
||||
{"Asia/Makassar", "WITA-8"},
|
||||
{"Asia/Manila", "PST-8"},
|
||||
{"Asia/Muscat", "<+04>-4"},
|
||||
{"Asia/Nicosia", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Asia/Novokuznetsk", "<+07>-7"},
|
||||
{"Asia/Novosibirsk", "<+07>-7"},
|
||||
{"Asia/Omsk", "<+06>-6"},
|
||||
{"Asia/Oral", "<+05>-5"},
|
||||
{"Asia/Phnom_Penh", "<+07>-7"},
|
||||
{"Asia/Pontianak", "WIB-7"},
|
||||
{"Asia/Pyongyang", "KST-9"},
|
||||
{"Asia/Qatar", "<+03>-3"},
|
||||
{"Asia/Qyzylorda", "<+05>-5"},
|
||||
{"Asia/Riyadh", "<+03>-3"},
|
||||
{"Asia/Sakhalin", "<+11>-11"},
|
||||
{"Asia/Samarkand", "<+05>-5"},
|
||||
{"Asia/Seoul", "KST-9"},
|
||||
{"Asia/Shanghai", "CST-8"},
|
||||
{"Asia/Singapore", "<+08>-8"},
|
||||
{"Asia/Srednekolymsk", "<+11>-11"},
|
||||
{"Asia/Taipei", "CST-8"},
|
||||
{"Asia/Tashkent", "<+05>-5"},
|
||||
{"Asia/Tbilisi", "<+04>-4"},
|
||||
{"Asia/Tehran", "<+0330>-3:30"},
|
||||
{"Asia/Thimphu", "<+06>-6"},
|
||||
{"Asia/Tokyo", "JST-9"},
|
||||
{"Asia/Tomsk", "<+07>-7"},
|
||||
{"Asia/Ulaanbaatar", "<+08>-8"},
|
||||
{"Asia/Urumqi", "<+06>-6"},
|
||||
{"Asia/Ust-Nera", "<+10>-10"},
|
||||
{"Asia/Vientiane", "<+07>-7"},
|
||||
{"Asia/Vladivostok", "<+10>-10"},
|
||||
{"Asia/Yakutsk", "<+09>-9"},
|
||||
{"Asia/Yangon", "<+0630>-6:30"},
|
||||
{"Asia/Yekaterinburg", "<+05>-5"},
|
||||
{"Asia/Yerevan", "<+04>-4"},
|
||||
{"Atlantic/Azores", "<-01>1<+00>,M3.5.0/0,M10.5.0/1"},
|
||||
{"Atlantic/Bermuda", "AST4ADT,M3.2.0,M11.1.0"},
|
||||
{"Atlantic/Canary", "WET0WEST,M3.5.0/1,M10.5.0"},
|
||||
{"Atlantic/Cape_Verde", "<-01>1"},
|
||||
{"Atlantic/Faroe", "WET0WEST,M3.5.0/1,M10.5.0"},
|
||||
{"Atlantic/Madeira", "WET0WEST,M3.5.0/1,M10.5.0"},
|
||||
{"Atlantic/Reykjavik", "GMT0"},
|
||||
{"Atlantic/South_Georgia", "<-02>2"},
|
||||
{"Atlantic/St_Helena", "GMT0"},
|
||||
{"Atlantic/Stanley", "<-03>3"},
|
||||
{"Australia/Adelaide", "ACST-9:30ACDT,M10.1.0,M4.1.0/3"},
|
||||
{"Australia/Brisbane", "AEST-10"},
|
||||
{"Australia/Broken_Hill", "ACST-9:30ACDT,M10.1.0,M4.1.0/3"},
|
||||
{"Australia/Currie", "AEST-10AEDT,M10.1.0,M4.1.0/3"},
|
||||
{"Australia/Darwin", "ACST-9:30"},
|
||||
{"Australia/Eucla", "<+0845>-8:45"},
|
||||
{"Australia/Hobart", "AEST-10AEDT,M10.1.0,M4.1.0/3"},
|
||||
{"Australia/Lindeman", "AEST-10"},
|
||||
{"Australia/Lord_Howe", "<+1030>-10:30<+11>-11,M10.1.0,M4.1.0"},
|
||||
{"Australia/Melbourne", "AEST-10AEDT,M10.1.0,M4.1.0/3"},
|
||||
{"Australia/Perth", "AWST-8"},
|
||||
{"Australia/Sydney", "AEST-10AEDT,M10.1.0,M4.1.0/3"},
|
||||
{"Etc/GMT", "GMT0"},
|
||||
{"Etc/GMT+0", "GMT0"},
|
||||
{"Etc/GMT+1", "<-01>1"},
|
||||
{"Etc/GMT+10", "<-10>10"},
|
||||
{"Etc/GMT+11", "<-11>11"},
|
||||
{"Etc/GMT+12", "<-12>12"},
|
||||
{"Etc/GMT+2", "<-02>2"},
|
||||
{"Etc/GMT+3", "<-03>3"},
|
||||
{"Etc/GMT+4", "<-04>4"},
|
||||
{"Etc/GMT+5", "<-05>5"},
|
||||
{"Etc/GMT+6", "<-06>6"},
|
||||
{"Etc/GMT+7", "<-07>7"},
|
||||
{"Etc/GMT+8", "<-08>8"},
|
||||
{"Etc/GMT+9", "<-09>9"},
|
||||
{"Etc/GMT-0", "GMT0"},
|
||||
{"Etc/GMT-1", "<+01>-1"},
|
||||
{"Etc/GMT-10", "<+10>-10"},
|
||||
{"Etc/GMT-11", "<+11>-11"},
|
||||
{"Etc/GMT-12", "<+12>-12"},
|
||||
{"Etc/GMT-13", "<+13>-13"},
|
||||
{"Etc/GMT-14", "<+14>-14"},
|
||||
{"Etc/GMT-2", "<+02>-2"},
|
||||
{"Etc/GMT-3", "<+03>-3"},
|
||||
{"Etc/GMT-4", "<+04>-4"},
|
||||
{"Etc/GMT-5", "<+05>-5"},
|
||||
{"Etc/GMT-6", "<+06>-6"},
|
||||
{"Etc/GMT-7", "<+07>-7"},
|
||||
{"Etc/GMT-8", "<+08>-8"},
|
||||
{"Etc/GMT-9", "<+09>-9"},
|
||||
{"Etc/GMT0", "GMT0"},
|
||||
{"Etc/Greenwich", "GMT0"},
|
||||
{"Etc/UCT", "UTC0"},
|
||||
{"Etc/UTC", "UTC0"},
|
||||
{"Etc/Universal", "UTC0"},
|
||||
{"Etc/Zulu", "UTC0"},
|
||||
{"Europe/Amsterdam", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Andorra", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Astrakhan", "<+04>-4"},
|
||||
{"Europe/Athens", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Belgrade", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Berlin", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Bratislava", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Brussels", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Bucharest", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Budapest", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Busingen", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Chisinau", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Copenhagen", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Dublin", "IST-1GMT0,M10.5.0,M3.5.0/1"},
|
||||
{"Europe/Gibraltar", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Guernsey", "GMT0BST,M3.5.0/1,M10.5.0"},
|
||||
{"Europe/Helsinki", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Isle_of_Man", "GMT0BST,M3.5.0/1,M10.5.0"},
|
||||
{"Europe/Istanbul", "<+03>-3"},
|
||||
{"Europe/Jersey", "GMT0BST,M3.5.0/1,M10.5.0"},
|
||||
{"Europe/Kaliningrad", "EET-2"},
|
||||
{"Europe/Kiev", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Kirov", "MSK-3"},
|
||||
{"Europe/Lisbon", "WET0WEST,M3.5.0/1,M10.5.0"},
|
||||
{"Europe/Ljubljana", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/London", "GMT0BST,M3.5.0/1,M10.5.0"},
|
||||
{"Europe/Luxembourg", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Madrid", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Malta", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Mariehamn", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Minsk", "<+03>-3"},
|
||||
{"Europe/Monaco", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Moscow", "MSK-3"},
|
||||
{"Europe/Oslo", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Paris", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Podgorica", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Prague", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Riga", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Rome", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Samara", "<+04>-4"},
|
||||
{"Europe/San_Marino", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Sarajevo", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Saratov", "<+04>-4"},
|
||||
{"Europe/Simferopol", "MSK-3"},
|
||||
{"Europe/Skopje", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Sofia", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Stockholm", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Tallinn", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Tirane", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Ulyanovsk", "<+04>-4"},
|
||||
{"Europe/Uzhgorod", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Vaduz", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Vatican", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Vienna", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Vilnius", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Volgograd", "MSK-3"},
|
||||
{"Europe/Warsaw", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Zagreb", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Europe/Zaporozhye", "EET-2EEST,M3.5.0/3,M10.5.0/4"},
|
||||
{"Europe/Zurich", "CET-1CEST,M3.5.0,M10.5.0/3"},
|
||||
{"Indian/Antananarivo", "EAT-3"},
|
||||
{"Indian/Chagos", "<+06>-6"},
|
||||
{"Indian/Christmas", "<+07>-7"},
|
||||
{"Indian/Cocos", "<+0630>-6:30"},
|
||||
{"Indian/Comoro", "EAT-3"},
|
||||
{"Indian/Kerguelen", "<+05>-5"},
|
||||
{"Indian/Mahe", "<+04>-4"},
|
||||
{"Indian/Maldives", "<+05>-5"},
|
||||
{"Indian/Mauritius", "<+04>-4"},
|
||||
{"Indian/Mayotte", "EAT-3"},
|
||||
{"Indian/Reunion", "<+04>-4"},
|
||||
{"Pacific/Apia", "<+13>-13"},
|
||||
{"Pacific/Auckland", "NZST-12NZDT,M9.5.0,M4.1.0/3"},
|
||||
{"Pacific/Bougainville", "<+11>-11"},
|
||||
{"Pacific/Chatham", "<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45"},
|
||||
{"Pacific/Chuuk", "<+10>-10"},
|
||||
{"Pacific/Easter", "<-06>6<-05>,M9.1.6/22,M4.1.6/22"},
|
||||
{"Pacific/Efate", "<+11>-11"},
|
||||
{"Pacific/Enderbury", "<+13>-13"},
|
||||
{"Pacific/Fakaofo", "<+13>-13"},
|
||||
{"Pacific/Fiji", "<+12>-12"},
|
||||
{"Pacific/Funafuti", "<+12>-12"},
|
||||
{"Pacific/Galapagos", "<-06>6"},
|
||||
{"Pacific/Gambier", "<-09>9"},
|
||||
{"Pacific/Guadalcanal", "<+11>-11"},
|
||||
{"Pacific/Guam", "ChST-10"},
|
||||
{"Pacific/Honolulu", "HST10"},
|
||||
{"Pacific/Kiritimati", "<+14>-14"},
|
||||
{"Pacific/Kosrae", "<+11>-11"},
|
||||
{"Pacific/Kwajalein", "<+12>-12"},
|
||||
{"Pacific/Majuro", "<+12>-12"},
|
||||
{"Pacific/Marquesas", "<-0930>9:30"},
|
||||
{"Pacific/Midway", "SST11"},
|
||||
{"Pacific/Nauru", "<+12>-12"},
|
||||
{"Pacific/Niue", "<-11>11"},
|
||||
{"Pacific/Norfolk", "<+11>-11<+12>,M10.1.0,M4.1.0/3"},
|
||||
{"Pacific/Noumea", "<+11>-11"},
|
||||
{"Pacific/Pago_Pago", "SST11"},
|
||||
{"Pacific/Palau", "<+09>-9"},
|
||||
{"Pacific/Pitcairn", "<-08>8"},
|
||||
{"Pacific/Pohnpei", "<+11>-11"},
|
||||
{"Pacific/Port_Moresby", "<+10>-10"},
|
||||
{"Pacific/Rarotonga", "<-10>10"},
|
||||
{"Pacific/Saipan", "ChST-10"},
|
||||
{"Pacific/Tahiti", "<-10>10"},
|
||||
{"Pacific/Tarawa", "<+12>-12"},
|
||||
{"Pacific/Tongatapu", "<+13>-13"},
|
||||
{"Pacific/Wake", "<+12>-12"},
|
||||
{"Pacific/Wallis", "<+12>-12"},
|
||||
};
|
||||
|
||||
inline int emsesp_tz_zone_cmp(const void * key, const void * element) {
|
||||
return strcmp(static_cast<const char *>(key), static_cast<const EmsespTzZone *>(element)->label);
|
||||
}
|
||||
|
||||
// Returns the POSIX TZ string for an IANA label, or nullptr if unknown.
|
||||
inline const char * emsesp_tz_format_for_label(const char * label) {
|
||||
if (label == nullptr || *label == '\0') {
|
||||
return nullptr;
|
||||
}
|
||||
const auto * found = static_cast<const EmsespTzZone *>(
|
||||
bsearch(label, EMSESP_TZ_ZONES, EMSESP_TZ_ZONE_COUNT, sizeof(EmsespTzZone), emsesp_tz_zone_cmp));
|
||||
return found != nullptr ? found->format : nullptr;
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
#define EMSESP_APP_VERSION "3.9.0-dev.19"
|
||||
#define EMSESP_APP_VERSION "3.9.0-dev.20"
|
||||
|
||||
Reference in New Issue
Block a user