|
| 1 | +# Developer Notes |
| 2 | + |
| 3 | +Information which are useful for developers and maintainers of the AceTime |
| 4 | +library. |
| 5 | + |
| 6 | +## Zone DB Files |
| 7 | + |
| 8 | +As explained in the README.md, the AceTime library comes with 2 versions of the |
| 9 | +[TZ Data](https://www.iana.org/time-zones): |
| 10 | + |
| 11 | +* `src/ace_time/zonedb/*`: files used by the `BasicZoneProcessor` class |
| 12 | +* `src/ace_time/zonedbx/*`: files used by the `ExtendedZoneProcessor` class |
| 13 | + |
| 14 | +There are 2 main files in these directories: |
| 15 | + |
| 16 | +* `zone_infos.h', `zone_infos.cpp` |
| 17 | +* `zone_policies.h`, `zone_policies.cpp` |
| 18 | + |
| 19 | +The format and meaning of these files are probably best explained in the header |
| 20 | +files: |
| 21 | + |
| 22 | +* `src/ace_time/internal/ZoneInfo.h` |
| 23 | +* `src/ace_time/internal/ZonePolicy.h` |
| 24 | + |
| 25 | +Some of the tricky encoding schemes were created to preserve resolution, while |
| 26 | +keeping the binary size of the data structures as small as possible. For |
| 27 | +example, these files are able to support DST transitions with a 1-minute |
| 28 | +resolution, but the DST offsets have only a 15-minute resolution. Fortunately, |
| 29 | +these limitations are sufficient to represent all time zones since about 1972. |
| 30 | + |
| 31 | +Other bits of information are added by the code generator as comments in the |
| 32 | +generated files and some of these are explained below. |
| 33 | + |
| 34 | +### `zone_infos.h` |
| 35 | + |
| 36 | +This file contains one entry of the `basic::ZoneInfo` or |
| 37 | +`extended::ZoneInfo` data structure for each supported time zone. |
| 38 | + |
| 39 | +The zone identifier is named `kZone{region}_{city}`, where the |
| 40 | +`{region}_{city}` comes directly from the TZ Database. Some minor character |
| 41 | +transformations are applied to create an valid C++ identifier. For example, all |
| 42 | +dashes `-` are converted to underscore `_`. |
| 43 | + |
| 44 | +The `kTzDatabaseVersion` string constant identifies the version of the TZ |
| 45 | +Database that was used to generate these files, e.g. "2019a". |
| 46 | + |
| 47 | +The `kZoneContext` variable points to an instance of `common::ZoneContext` |
| 48 | +which identifies the `startYear` and `endYear` of the current database. These |
| 49 | +will normally be 2000 and 2050 respectively, but a custom version of the |
| 50 | +zonedb files could be generated whose startYear and endYear could be smaller (to |
| 51 | +produce smaller ZoneDB files). |
| 52 | + |
| 53 | +Near end of the `zone_info.h` file, we list the zones which were |
| 54 | +deliberately excluded by the tool. |
| 55 | + |
| 56 | +Also at the end of the `zone_info.h` file, there may be warnings about |
| 57 | +known inaccuracies for a particular zone. |
| 58 | + |
| 59 | +### `zone_infos.cpp` |
| 60 | + |
| 61 | +Each zone entry in the `zone_info.cpp` contains a comment section that |
| 62 | +describes some metadata about the given entry. For example, the entry for |
| 63 | +`zonedb::kZoneEraAmerica_Los_Angeles` contains the following, showing how |
| 64 | +much memory it will consume on the 8-bit Arduino controllers and the 32-bit |
| 65 | +Arduino controllers: |
| 66 | + |
| 67 | +* `// Zone name: America/Los_Angeles` |
| 68 | +* `// Era count: 1` |
| 69 | +* `// Strings: 24` |
| 70 | +* `// Memory (8-bit): 43` |
| 71 | +* `// Memory (32-bit): 53` |
| 72 | + |
| 73 | +### `zone_policies.h` |
| 74 | + |
| 75 | +An entry in `zone_info.cpp` may refer to a zone policy defined in |
| 76 | +`zone_policies.h`. For example, the `kZoneAmerica_Los_Angeles` has a pointer |
| 77 | +to a `kPolicyUS` data structure which is defined in `zone_policies.h`. |
| 78 | + |
| 79 | +Each policy entry starts with a comment secion that contains some metadata |
| 80 | +about the policy. For example: |
| 81 | +``` |
| 82 | +// Policy name: US |
| 83 | +// Rule count: 5 |
| 84 | +// Memory (8-bit): 51 |
| 85 | +// Memory (32-bit): 55 |
| 86 | +``` |
| 87 | +Just like `zone_infos.cpp`, the Memory section describes the amount of static |
| 88 | +RAM consumed by the particular `ZonePolicy` data structure (and associated |
| 89 | +`ZoneRule`. |
| 90 | + |
| 91 | +## Upgrading ZoneInfo Files to a New TZDB Version |
| 92 | + |
| 93 | +About 2-4 times a year, a new TZDB version is released. Here are some notes |
| 94 | +(mostly for myself) on how to create a new release after a new TZDB version is |
| 95 | +available. |
| 96 | + |
| 97 | +* Update the TZDB repo (https://github.com/eggert/tz). This should be a |
| 98 | + sibling to the `AceTime` repo (since it will cause the least problems |
| 99 | + for various internal scripts): |
| 100 | + * `$ cd ../tz` |
| 101 | + * `$ git pull` |
| 102 | + * Check that the correct tag is pulled (e.g. `2020c` tag if that's the |
| 103 | + version that we want to upgrade to). |
| 104 | +* Update the Hinnant date repo (https://github.com:HowardHinnant/date). This |
| 105 | + should be a sibling to the `AceTime` repo: |
| 106 | + * `$ cd ../date` |
| 107 | + * `$ git pull` |
| 108 | +* Verify that `AceTime` and Hinnant `date` agree with each other using the |
| 109 | + same TZDB version. |
| 110 | + * BasicHinnantDateTest |
| 111 | + * `$ cd tests/validation/BasicHinnantDateTest` |
| 112 | + * Update the `TZ_VERSION` variable in the `Makefile` with the commit tag |
| 113 | + of the new TZDB version. (e.g. `TZ_VERSION = 2020c`). |
| 114 | + * `$ make clean` |
| 115 | + * `$ make` |
| 116 | + * `$ ./BasicHinnantDateTest.out | grep failed` |
| 117 | + * There should be no failures: `TestRunner summary: 268 passed, 0 |
| 118 | + failed, 0 skipped, 0 timed out, out of 268 test(s).` |
| 119 | + * ExtendedHinnantDateTest |
| 120 | + * `$ cd tests/validation/ExtendedHinnantDateTest` |
| 121 | + * Update the `TZ_VERSION` variable in the `Makefile` with the commit tag |
| 122 | + of the new TZDB version. (e.g. `TZ_VERSION = 2020c`). |
| 123 | + * `$ make clean` |
| 124 | + * `$ make` |
| 125 | + * `$ ./ExtendedHinnantDateTest.out | grep failed` |
| 126 | + * There should be no failures: `TestRunner summary: 387 passed, 0 |
| 127 | + failed, 0 skipped, 0 timed out, out of 387 test(s).` |
| 128 | +* Update the `src/ace_time/zonedb` and `zonedbx` zone info files: |
| 129 | + * zonedb |
| 130 | + * `$ cd src/ace_time/zonedb` |
| 131 | + * Update the `TZ_VERSION` in the `Makefile`. |
| 132 | + * `$ make clean` |
| 133 | + * `$ make` |
| 134 | + * zonedbx |
| 135 | + * `$ cd src/ace_time/zonedbx` |
| 136 | + * Update the `TZ_VERSION` in the `Makefile`. |
| 137 | + * `$ make clean` |
| 138 | + * `$ make` |
| 139 | +* Update the CHANGELOG.md. |
| 140 | +* Commit the changes to git |
| 141 | + * `$ git add ...` |
| 142 | + * `$ git commit -m "..."` |
| 143 | + |
| 144 | +There are 6 other validation tests in `tests/validation` that compare AceTime |
| 145 | +with other 3rd party librarties (Python pytz, Python dateutil, and Java date). |
| 146 | +Unfortunately, they all seem to use the underlying TZDB version provided by the |
| 147 | +Operating System, and I have not been able to figure out how to manually update |
| 148 | +this dependency manually. When a new TZDB is released, all of these other tests |
| 149 | +will fail until the underying timezone database of the OS is updated. |
| 150 | + |
| 151 | +## Release Process |
| 152 | + |
| 153 | +* Update and commit the version numbers in various files: |
| 154 | + * `src/AceTime.h` |
| 155 | + * `README.md` |
| 156 | + * `USER_GUIDE.md` |
| 157 | + * `docs/doxygen.cfg` |
| 158 | + * `library.properties` |
| 159 | + * `CHANGELOG.md` |
| 160 | + * `$ git commit -m "..."` |
| 161 | +* Update and commit the Doxygen docs. This is done as a separate git commit |
| 162 | + because the Doxygen changes are often so large that they obscure all other |
| 163 | + important changes to the code base: |
| 164 | + * `$ cd docs` |
| 165 | + * `$ make clean` |
| 166 | + * `$ make` |
| 167 | + * `$ git add .` |
| 168 | + * `$ git commit -m "..."` |
| 169 | +* Merge the `develop` branch into `master`. |
| 170 | + * Normally I do this with a PR on GitHub to keep an audit trail. |
| 171 | + * Go to https://github.com/bxparks/AceTime. |
| 172 | + * Create a Pull Request from `develop` to `master` |
| 173 | + * Approve and merge the PR. |
| 174 | +* Create a new Release. |
| 175 | + * Go to https://github.com/bxparks/AceTime |
| 176 | + * Click on "Releases" |
| 177 | + * Click on "Draft a new release" |
| 178 | + * Enter a tag version (e.g. 'v1.2`), targeting the `master` branch. |
| 179 | + * Enter the release title. |
| 180 | + * Enter the release notes. I normally just copy and paste the latest changes |
| 181 | + from `CHANGELOG.md`. |
| 182 | + * Click Publish release. |
0 commit comments