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)
set(TZCODE_PROJECT tzcode-iana)
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(TZCODE_SRC ${PROJECT_SOURCE_DIR}/src/lib/tzcode)
set(TZDATA_FULL_TARGET
${TZCODE_PREFIX}/src/${TZCODE_PROJECT}/${TZDATA_TARGET})
......@@ -15,7 +17,9 @@ ExternalProject_Add(${TZCODE_PROJECT}
GIT_TAG 2022a
GIT_SHALLOW YES
EXCLUDE_FROM_ALL 1
INSTALL_DIR ${TZCODE_BUILD_DIR}/install
PREFIX ${TZCODE_PREFIX_DIR}
UPDATE_COMMAND ""
CONFIGURE_COMMAND ""
......@@ -30,3 +34,21 @@ ExternalProject_Add(${TZCODE_PROJECT}
INSTALL_COMMAND make DESTDIR=<INSTALL_DIR> install
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 {
};
my %ZoneAbbrevs;
my %ZoneAbbrevNames;
# read zone-abbrevs.txt with definition of all currently known
# timezone abbreviations.
......@@ -176,36 +177,43 @@ sub read_abbrevs_file($) {
}
$ZoneAbbrevs{$encoded} = [ $flags, $offset, $name ];
$ZoneAbbrevNames{$name}++;
}
}
my %ZoneNames;
my %ZoneIds;
my %Aliases;
sub read_zi_file($) {
my $filename = shift;
open( my $fh, '<:raw', $filename )
or die qq<Could not open '$filename' for reading: '$!'>;
my $zone;
my $format;
while (<$fh>) {
next if /^#/;
if (/^Zone\s+([A-Za-z\-\_\/]+)\s+/) {
$zone = $1;
$ZoneNames{$zone}++ if $zone =~ q|/|;
next;
my $zone = $1;
next unless $zone =~ q|/|;
$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() {
printf "/* Automatically generated by gen-zone-abbrevs.pl */\n";
# first we generate abbreviations list
# first we generate abbreviations list
sub gen_abbrevs() {
foreach my $encoded ( sort { $a <=> $b } keys %ZoneAbbrevs ) {
my ( $flags, $offset, $name ) = @{ $ZoneAbbrevs{$encoded} };
my $nextid = next_id($name);
$ZoneIds{$nextid} = $name;
if ( $flags != 0 ) {
my @names;
......@@ -221,14 +229,34 @@ sub gen_header() {
printf "ZONE_ABBREV(%4d, %4d, \"%s\", %s)\n",
$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) {
my $nextid = next_id($zonename);
$ZoneIds{$zonename} = $nextid;
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_zi_file($tzdata_zi_file);
gen_header();
......@@ -15,8 +15,9 @@
#include <unistd.h>
#define LOCALTIME_IMPLEMENTATION
#include "private.h"
#include "tzfile.h"
#include "tzcode.h"
#include <fcntl.h>
#ifndef TZ_ABBR_MAX_LEN
......@@ -66,10 +67,10 @@
#define WILDABBR " "
#endif /* !defined WILDABBR */
static const char wildabbr[] = WILDABBR;
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.
** Default to US rules as of 2017-05-07.
......
......@@ -31,7 +31,9 @@ timezone_flags(const struct date_time_zone *zone)
static const char * zone_names[] = {
#define ZONE_ABBREV(id, offset, name, flags) [id] = name,
#define ZONE_UNIQUE(id, name) [id] = name,
#define ZONE_ALIAS(id, alias, name)
#include "timezones.h"
#undef ZONE_ALIAS
#undef ZONE_UNIQUE
#undef ZONE_ABBREV
};
......@@ -45,9 +47,10 @@ timezone_name(int64_t index)
static struct date_time_zone zone_abbrevs[] = {
#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"
#undef ZONE_ALIAS
#undef ZONE_UNIQUE
#undef ZONE_ABBREV
};
......
......@@ -17,6 +17,8 @@ enum {
TZ_MILITARY = 0x04,
TZ_AMBIGUOUS = 0x08,
TZ_NYI = 0x10,
TZ_OLSON = 0x20,
TZ_ALIAS = 0x40,
};
/**
......
This diff is collapsed.
......@@ -66,6 +66,13 @@ char *
tnt_strptime(const char *__restrict buf, const char *__restrict fmt,
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)
} /* extern "C" */
#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