Skip to content
Snippets Groups Projects
Commit b6ff1978 authored by Timur Safin's avatar Timur Safin Committed by Kirill Yukhin
Browse files

datetime: primary and aliases zones in Olson

* localtime.c refactored to make tzalloc/tzfree public;
* Modified Perl script to generate primary Olson timezones and aliases.
  Get rid of NYI;

NO_DOC=refactoring
NO_CHANGELOG=refactoring
NO_TEST=refactoring
parent d3acfece
No related branches found
No related tags found
No related merge requests found
...@@ -4,8 +4,10 @@ target_link_libraries(tzcode) ...@@ -4,8 +4,10 @@ target_link_libraries(tzcode)
set(TZCODE_PROJECT tzcode-iana) set(TZCODE_PROJECT tzcode-iana)
set(TZCODE_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(TZCODE_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(TZCODE_PREFIX ${TZCODE_BUILD_DIR}/tz) set(TZCODE_PREFIX_DIR tz)
set(TZCODE_PREFIX ${TZCODE_BUILD_DIR}/${TZCODE_PREFIX_DIR})
set(TZDATA_TARGET main.zi) set(TZDATA_TARGET main.zi)
set(TZCODE_SRC ${PROJECT_SOURCE_DIR}/src/lib/tzcode)
set(TZDATA_FULL_TARGET set(TZDATA_FULL_TARGET
${TZCODE_PREFIX}/src/${TZCODE_PROJECT}/${TZDATA_TARGET}) ${TZCODE_PREFIX}/src/${TZCODE_PROJECT}/${TZDATA_TARGET})
...@@ -15,7 +17,9 @@ ExternalProject_Add(${TZCODE_PROJECT} ...@@ -15,7 +17,9 @@ ExternalProject_Add(${TZCODE_PROJECT}
GIT_TAG 2022a GIT_TAG 2022a
GIT_SHALLOW YES GIT_SHALLOW YES
EXCLUDE_FROM_ALL 1
INSTALL_DIR ${TZCODE_BUILD_DIR}/install INSTALL_DIR ${TZCODE_BUILD_DIR}/install
PREFIX ${TZCODE_PREFIX_DIR}
UPDATE_COMMAND "" UPDATE_COMMAND ""
CONFIGURE_COMMAND "" CONFIGURE_COMMAND ""
...@@ -30,3 +34,21 @@ ExternalProject_Add(${TZCODE_PROJECT} ...@@ -30,3 +34,21 @@ ExternalProject_Add(${TZCODE_PROJECT}
INSTALL_COMMAND make DESTDIR=<INSTALL_DIR> install INSTALL_COMMAND make DESTDIR=<INSTALL_DIR> install
BUILD_BYPRODUCTS ${TZDATA_FULL_TARGET} BUILD_BYPRODUCTS ${TZDATA_FULL_TARGET}
) )
find_program(PERL perl)
add_custom_target(gen-timezones DEPENDS ${TZCODE_PROJECT})
add_custom_command(TARGET gen-timezones
COMMAND
${PERL} ${TZCODE_SRC}/gen-zone-abbrevs.pl ${TZCODE_SRC}/zone-abbrevs.txt
${TZDATA_FULL_TARGET} > ${TZCODE_SRC}/timezones.h
COMMENT "Generating timezones.h"
)
# We excluded build of gen-timezones and tzcode-iana (main.zi) targets
# from ALL dependencies (see EXCLUDE_FROM_ALL=1) if you, by either reason
# need to regenerate timezones.h then invoke target manually:
# ```sh
# make gen-timezones VERBOSE=1
# ```
# it will regenerate `timezones.h` in-place, in their repository location.
...@@ -129,6 +129,7 @@ my $EntryRx = do { ...@@ -129,6 +129,7 @@ my $EntryRx = do {
}; };
my %ZoneAbbrevs; my %ZoneAbbrevs;
my %ZoneAbbrevNames;
# read zone-abbrevs.txt with definition of all currently known # read zone-abbrevs.txt with definition of all currently known
# timezone abbreviations. # timezone abbreviations.
...@@ -176,36 +177,43 @@ sub read_abbrevs_file($) { ...@@ -176,36 +177,43 @@ sub read_abbrevs_file($) {
} }
$ZoneAbbrevs{$encoded} = [ $flags, $offset, $name ]; $ZoneAbbrevs{$encoded} = [ $flags, $offset, $name ];
$ZoneAbbrevNames{$name}++;
} }
} }
my %ZoneNames; my %ZoneNames;
my %ZoneIds;
my %Aliases;
sub read_zi_file($) { sub read_zi_file($) {
my $filename = shift; my $filename = shift;
open( my $fh, '<:raw', $filename ) open( my $fh, '<:raw', $filename )
or die qq<Could not open '$filename' for reading: '$!'>; or die qq<Could not open '$filename' for reading: '$!'>;
my $zone;
my $format;
while (<$fh>) { while (<$fh>) {
next if /^#/; next if /^#/;
if (/^Zone\s+([A-Za-z\-\_\/]+)\s+/) { if (/^Zone\s+([A-Za-z\-\_\/]+)\s+/) {
$zone = $1; my $zone = $1;
$ZoneNames{$zone}++ if $zone =~ q|/|; next unless $zone =~ q|/|;
next; $ZoneNames{$zone}++;
} elsif (/^[#]?Link\s+(\S+)\s+(\S+)/) {
my $zone = $1;
my $link = $2;
# do not create alias if it's known abbreviation
next if defined $ZoneAbbrevNames{$link};
$Aliases{$link} = $zone;
} }
} }
} }
sub gen_header() { # first we generate abbreviations list
printf "/* Automatically generated by gen-zone-abbrevs.pl */\n"; sub gen_abbrevs() {
# first we generate abbreviations list
foreach my $encoded ( sort { $a <=> $b } keys %ZoneAbbrevs ) { foreach my $encoded ( sort { $a <=> $b } keys %ZoneAbbrevs ) {
my ( $flags, $offset, $name ) = @{ $ZoneAbbrevs{$encoded} }; my ( $flags, $offset, $name ) = @{ $ZoneAbbrevs{$encoded} };
my $nextid = next_id($name); my $nextid = next_id($name);
$ZoneIds{$nextid} = $name;
if ( $flags != 0 ) { if ( $flags != 0 ) {
my @names; my @names;
...@@ -221,14 +229,34 @@ sub gen_header() { ...@@ -221,14 +229,34 @@ sub gen_header() {
printf "ZONE_ABBREV(%4d, %4d, \"%s\", %s)\n", printf "ZONE_ABBREV(%4d, %4d, \"%s\", %s)\n",
$nextid, $offset, $name, $flags; $nextid, $offset, $name, $flags;
} }
}
# second we enumerate all known from main.zi primary zone names # second we enumerate all known from main.zi primary zone names
sub gen_primary_zones() {
foreach my $zonename (sort keys %ZoneNames) { foreach my $zonename (sort keys %ZoneNames) {
my $nextid = next_id($zonename); my $nextid = next_id($zonename);
$ZoneIds{$zonename} = $nextid;
printf "ZONE_UNIQUE(%4d, \"%s\")\n", $nextid, $zonename; printf "ZONE_UNIQUE(%4d, \"%s\")\n", $nextid, $zonename;
} }
} }
# third we enumerate all aliases for primary zones
sub gen_aliases() {
foreach my $alias ( sort keys %Aliases ) {
my $zonename = $Aliases{$alias};
printf "ZONE_ALIAS(%4d, \"%s\", \"%s\")\n", $ZoneIds{$zonename},
$alias, $zonename;
}
}
sub gen_header() {
printf "/* Automatically generated by gen-zone-abbrevs.pl */\n";
gen_abbrevs();
gen_primary_zones();
gen_aliases();
}
read_abbrevs_file($zone_abbrevs_file); read_abbrevs_file($zone_abbrevs_file);
read_zi_file($tzdata_zi_file); read_zi_file($tzdata_zi_file);
gen_header(); gen_header();
...@@ -15,8 +15,9 @@ ...@@ -15,8 +15,9 @@
#include <unistd.h> #include <unistd.h>
#define LOCALTIME_IMPLEMENTATION #define LOCALTIME_IMPLEMENTATION
#include "private.h" #include "private.h"
#include "tzfile.h" #include "tzfile.h"
#include "tzcode.h"
#include <fcntl.h> #include <fcntl.h>
#ifndef TZ_ABBR_MAX_LEN #ifndef TZ_ABBR_MAX_LEN
...@@ -66,10 +67,10 @@ ...@@ -66,10 +67,10 @@
#define WILDABBR " " #define WILDABBR " "
#endif /* !defined WILDABBR */ #endif /* !defined WILDABBR */
static const char wildabbr[] = WILDABBR;
static const char gmt[] = "GMT"; static const char gmt[] = "GMT";
static const char wildabbr[] = WILDABBR;
/* /*
** The DST rules to use if TZ has no rules and we can't load TZDEFRULES. ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
** Default to US rules as of 2017-05-07. ** Default to US rules as of 2017-05-07.
......
...@@ -31,7 +31,9 @@ timezone_flags(const struct date_time_zone *zone) ...@@ -31,7 +31,9 @@ timezone_flags(const struct date_time_zone *zone)
static const char * zone_names[] = { static const char * zone_names[] = {
#define ZONE_ABBREV(id, offset, name, flags) [id] = name, #define ZONE_ABBREV(id, offset, name, flags) [id] = name,
#define ZONE_UNIQUE(id, name) [id] = name, #define ZONE_UNIQUE(id, name) [id] = name,
#define ZONE_ALIAS(id, alias, name)
#include "timezones.h" #include "timezones.h"
#undef ZONE_ALIAS
#undef ZONE_UNIQUE #undef ZONE_UNIQUE
#undef ZONE_ABBREV #undef ZONE_ABBREV
}; };
...@@ -45,9 +47,10 @@ timezone_name(int64_t index) ...@@ -45,9 +47,10 @@ timezone_name(int64_t index)
static struct date_time_zone zone_abbrevs[] = { static struct date_time_zone zone_abbrevs[] = {
#define ZONE_ABBREV(id, offset, name, flags) { name, id, flags, offset }, #define ZONE_ABBREV(id, offset, name, flags) { name, id, flags, offset },
#define ZONE_UNIQUE(id, name) { name, id, TZ_NYI, 0 }, #define ZONE_UNIQUE(id, name) { name, id, TZ_OLSON, 0 },
#define ZONE_ALIAS(id, alias, name) { alias, id, TZ_OLSON|TZ_ALIAS, 0 },
#include "timezones.h" #include "timezones.h"
#undef ZONE_ALIAS
#undef ZONE_UNIQUE #undef ZONE_UNIQUE
#undef ZONE_ABBREV #undef ZONE_ABBREV
}; };
......
...@@ -17,6 +17,8 @@ enum { ...@@ -17,6 +17,8 @@ enum {
TZ_MILITARY = 0x04, TZ_MILITARY = 0x04,
TZ_AMBIGUOUS = 0x08, TZ_AMBIGUOUS = 0x08,
TZ_NYI = 0x10, TZ_NYI = 0x10,
TZ_OLSON = 0x20,
TZ_ALIAS = 0x40,
}; };
/** /**
......
This diff is collapsed.
...@@ -66,6 +66,13 @@ char * ...@@ -66,6 +66,13 @@ char *
tnt_strptime(const char *__restrict buf, const char *__restrict fmt, tnt_strptime(const char *__restrict buf, const char *__restrict fmt,
struct tnt_tm *__restrict tm); struct tnt_tm *__restrict tm);
typedef struct state *timezone_t;
/** Find installed timezone definition and load it to memory */
timezone_t tzalloc(const char *);
/** Free loaded timezone definition */
void tzfree(timezone_t);
#if defined(__cplusplus) #if defined(__cplusplus)
} /* extern "C" */ } /* extern "C" */
#endif /* defined(__cplusplus) */ #endif /* defined(__cplusplus) */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment