gregjesl / brutezone Goto Github PK
View Code? Open in Web Editor NEWIANA timezone library for C
License: MIT License
IANA timezone library for C
License: MIT License
Instead of using a target for removing old timezone offsets (like in #21), I'd like to use a preprocessor definition that would filter out old timezone offsets (but leaving the current offset).
It would look something like
static const timezone_offset timezone_database_america_los_angeles[] =
{
#ifndef BRUTEZONE_FUTURE_ONLY
{0,-2880},
{9972000,-2520},
...
{1552212000,-2520},
{1572771600,-2880},
#endif
{1583661600,-2520},
{1604221200,-2880},
...
{2120119200,-2520},
{2140678800,-2880}
};
timezone_array
would also have to be updated based on the number of entries remaining for each time zone.
The advantage of this approach is that it would cooperate better with other build systems (like the EspressIf build chain).
Some memory-constrained applications may only require current and future times (and may not require times in the past). Removing times in the past will save memory.
The solution should add a target that automatically calls the correct generator command.
make test
does not appear to do anything:
$ cd brutezone
$ mkdir build
$ cd build
$ cmake ../
...
$ make
Scanning dependencies of target brutezone
[ 3%] Building C object CMakeFiles/brutezone.dir/src/timezone.c.o
[ 7%] Building C object CMakeFiles/brutezone.dir/src/timezone_impl.c.o
[ 11%] Linking C static library libbrutezone.a
[ 11%] Built target brutezone
Scanning dependencies of target tm_to_secs_test
[ 14%] Building C object test/CMakeFiles/tm_to_secs_test.dir/tm_to_secs.c.o
[ 18%] Linking C executable tm_to_secs_test
[ 18%] Built target tm_to_secs_test
Scanning dependencies of target timezone_current_local_time_test
[ 22%] Building C object test/CMakeFiles/timezone_current_local_time_test.dir/timezone_current_local_time.c.o
[ 25%] Linking C executable timezone_current_local_time_test
[ 25%] Built target timezone_current_local_time_test
Scanning dependencies of target timezone_secs_until_dow_test
[ 29%] Building C object test/CMakeFiles/timezone_secs_until_dow_test.dir/timezone_secs_until_dow.c.o
[ 33%] Linking C executable timezone_secs_until_dow_test
[ 33%] Built target timezone_secs_until_dow_test
Scanning dependencies of target secs_to_tm_test
[ 37%] Building C object test/CMakeFiles/secs_to_tm_test.dir/secs_to_tm.c.o
[ 40%] Linking C executable secs_to_tm_test
[ 40%] Built target secs_to_tm_test
Scanning dependencies of target add_day_test
[ 44%] Building C object test/CMakeFiles/add_day_test.dir/add_day.c.o
[ 48%] Linking C executable add_day_test
[ 48%] Built target add_day_test
Scanning dependencies of target timezone_local_time_test
[ 51%] Building C object test/CMakeFiles/timezone_local_time_test.dir/timezone_local_time.c.o
[ 55%] Linking C executable timezone_local_time_test
[ 55%] Built target timezone_local_time_test
Scanning dependencies of target subtract_day_test
[ 59%] Building C object test/CMakeFiles/subtract_day_test.dir/subtract_day.c.o
[ 62%] Linking C executable subtract_day_test
[ 62%] Built target subtract_day_test
Scanning dependencies of target timezone_gmt_time_test
[ 66%] Building C object test/CMakeFiles/timezone_gmt_time_test.dir/timezone_gmt_time.c.o
[ 70%] Linking C executable timezone_gmt_time_test
[ 70%] Built target timezone_gmt_time_test
Scanning dependencies of target timezone_secs_since_test
[ 74%] Building C object test/CMakeFiles/timezone_secs_since_test.dir/timezone_secs_since.c.o
[ 77%] Linking C executable timezone_secs_since_test
[ 77%] Built target timezone_secs_since_test
Scanning dependencies of target timezone_secs_since_dow_test
[ 81%] Building C object test/CMakeFiles/timezone_secs_since_dow_test.dir/timezone_secs_since_dow.c.o
[ 85%] Linking C executable timezone_secs_since_dow_test
[ 85%] Built target timezone_secs_since_dow_test
Scanning dependencies of target find_timezone_test
[ 88%] Building C object test/CMakeFiles/find_timezone_test.dir/find_timezone.c.o
[ 92%] Linking C executable find_timezone_test
[ 92%] Built target find_timezone_test
Scanning dependencies of target timezone_secs_until_test
[ 96%] Building C object test/CMakeFiles/timezone_secs_until_test.dir/timezone_secs_until.c.o
[100%] Linking C executable timezone_secs_until_test
[100%] Built target timezone_secs_until_test
$ make test
$ make test V=1
$ make test VERBOSE=1
make: Nothing to be done for 'test'.
$
This may be related to Issue 1. The typical pattern used by the test files appears to be, use assert
to crash a program. The problem is, Cmake defines -DNDEBUG
for release builds. The asserts are removed in release builds.
For example, all of the tests in add_day.c
are removed when building with Cmake in a standard configuration:
int main(void)
{
time_t gmtime;
struct tm tm;
// Get the time of 29 January 1970 at 3 AM
gmtime = (28 * 86400) + (10 * 3600) + (3 * 60) + 17;
// Convert to a tm
secs_to_tm(gmtime, &tm);
// Add a day
add_day(&tm);
// Verify the result
assert(tm.tm_year == 70);
assert(tm.tm_mon == 0);
assert(tm.tm_mday == 30);
assert(tm.tm_hour == 10);
assert(tm.tm_min == 3);
assert(tm.tm_sec == 17);
assert(tm.tm_wday == 5);
return 0;
}
From @huelsenfruchtzwerg's pull request (#17)
The offset for Africa/Monrovia before 1972 12:44:30 AM UTC is actually incorrect right now because it's stored as a 44 minutes, but correct would be 44:30 minutes. This could be addressed by storing the offset in seconds. Due to alignment, this shouldn't actually change the actual size of the generated table, at least on platforms where _Alignof(time_t) == sizeof(time_t). Testing around with the available platforms on godbolt, this appear to be most of them (x86, x86-64, arm, arm64, and from my own testing xtensa/esp32 as well), except AVR/Arduino unfortunately.
On the other hand, if we keep the offsets in minutes as a short (and live with Monrovia being incorrect or find another fix) we could use attribute((packed)) on timezone_offset to save a few byte per offset for a slight cpu-time cost, which adds up to quite a bit of size-savings (tested on my x86-64 machine, on 32bit platforms the savings would end up lower but still quite substantial).
Currently:
Africa/
is repeated 54 timesAmerica/
is repeated 166 timesAntarctica/
is repeated 12 timesAsia/
is repeated 98 timesAtlantic/
is repeated 12 timesAustralia/
is repeated 23 timesGrouping timezones by there continent and removing the continent predecessor in the string name should save kilobytes of space. Although this seems trivial, it can be very helpful on embedded systems.
find_timezone
would need to know how to split the continent from the input and target the correct group.
There are some timezones that are not defined by the continent/area approach (UTC and ROK, for example); these would need to be handled as well.
To save additional space, we could also look at packing each timezone_offset
array.
Currently, the Appveyor unit tests only run the ctest tests. Ideally, the Appveyor script would first run the generator and then run the unit tests. This would ensure the generator works as well.
Now that #12 is closed, make database
can be added as a dependency to ensure the correct timezone database is generated before the library is compiled.
While looking at the generator I was wondering why the single-offset timezones where handled as a special case, 'til I realized it was done to reuse them for multiple timezones.
I then started wondering if this optimization could be applied to larger timezones as well, and as it turns out a fair number of timezones are just aliases, even some bigger ones (e.g. Arctic/Longyearbyen is just an alias for Europe/Oslo (source), but currently is repeated completely).
I figure instead of treating the single-offset timezones as a special case, we could group all identical timezones regardless of number of offsets.
I had a quick crack at it, but I barely know any C# so I didn't manage to get something that compiles. But I guess it should be "relatively" easy using linq-group-by stuff?
At least personaly, I get tired of manually formating files. I like to just use clang-format to autoformat every file I work on and know it's correct.
I don't really care all that much about the specific style.
The unit test timezone_gmt_time
hangs when run.
Currently there is no feedback from the generator regarding the progress.
The following time zones fail the timezone_gmt_time.c
unit test:
America/Glace_Bay
America/Goose_Bay
America/Halifax
America/Havana
America/Moncton
America/St_Johns
America/Thule
Atlantic/Bermuda
Discovered when merging #3
@huelsenfruchtzwerg had some great adds, to include adding Doxygen support. The readme needs to be updated with the latest changes.
Hosting the Doxygen output in a /docs
folder is another option. This would allow browsing of the documentation via Github pages.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.