#pragma once
#include <panda/time/time.h>
namespace panda { namespace time {
const size_t TZNAME_MAX = 255; // max length of timezone name or POSIX rule (Europe/Moscow, ...)
enum tzswitch_t { TZSWITCH_DATE, TZSWITCH_JDAY, TZSWITCH_DAY };
struct tztrans {
ptime_t start; // time of transition
ptime_t local_start; // local time of transition (epoch+offset).
ptime_t local_end; // local time of transition's end (next transition epoch + MY offset).
ptime_t local_lower; // local_start or prev transition's local_end
ptime_t local_upper; // local_start or prev transition's local_end
int32_t offset; // offset from non-leap GMT
int32_t gmt_offset; // offset from leap GMT
int32_t delta; // offset minus previous transition's offset
int32_t isdst; // is DST in effect after this transition
int32_t leap_corr; // summary leap seconds correction at the moment
int32_t leap_delta; // delta leap seconds correction (0 if it's just a transition, != 0 if it's a leap correction)
ptime_t leap_end; // end of leap period (not including last second) = start + leap_delta
ptime_t leap_lend; // local_start + 2*leap_delta
union {
char abbrev[ZONE_ABBR_MAX+1]; // transition (zone) abbreviation
int64_t n_abbrev; // abbrev as int64_t
};
};
// rule for future (beyond transition list) dates and for abstract timezones
// http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
// --------------------------------------------------------------------------------------------
// 1 Jan OUTER ZONE OUTER END INNER ZONE INNER END OUTER ZONE 31 Dec
// --------------------------------------------------------------------------------------------
struct tzrulezone {
union {
char abbrev[ZONE_ABBR_MAX+1]; // zone abbreviation
int64_t n_abbrev; // abbrev as int64_t
};
int32_t offset; // offset from non-leap GMT
int32_t gmt_offset; // offset from leap GMT
int32_t isdst; // true if zone represents DST time
tzswitch_t type; // type of 'end' field
dt end; // dynamic date when this zone ends (only if hasdst=1)
};
struct tzrule {
uint32_t hasdst; // does this rule have DST switching
tzrulezone outer; // always present
tzrulezone inner; // only present if hasdst=1
int32_t max_offset; // max(outer.offset, inner.offset)
int32_t delta; // inner.offset - outer.offset
};
struct tzleap {
ptime_t time;
uint32_t correction;
};
struct tz {
private:
mutable size_t refcnt;
public:
char name[TZNAME_MAX+1];
tztrans* trans;
uint32_t trans_cnt;
tztrans ltrans; // trans[trans_cnt-1]
tzleap* leaps;
uint32_t leaps_cnt;
tzrule future;
mutable bool is_local; // if timezone is set as local at the moment
tz () : refcnt(1) {}
void retain () const { refcnt++; }
void release () const {
if (--refcnt <= 0) {
clear();
delete this;
}
}
void clear () const {
delete[] this->trans;
if (this->leaps_cnt > 0) delete[] this->leaps;
}
};
void tzset (const char* zonename = NULL);
const tz* tzget (const char*);
const tz* tzlocal ();
const char* tzdir ();
bool tzdir (const char*);
const char* tzsysdir ();
}}