time zone

group turbo_times_time_zone

Functions

inline bool load_time_zone(std::string_view name, TimeZone *tz)

Loads the named zone.

May perform I/O on the initial load of the named zone. If the name is invalid, or some other kind of error occurs, returns false and *tz is set to the UTC time zone.

Parameters:
  • name

  • tz

Returns:

inline TimeZone fixed_time_zone(int seconds)

`

Returns a TimeZone that is a fixed offset (seconds east) from UTC. Note: If the absolute value of the offset is greater than 24 hours you’ll get UTC (i.e., no offset) instead.

Parameters:

seconds

Returns:

inline TimeZone utc_time_zone()

Convenience method returning the UTC time zone.

Returns:

inline TimeZone local_time_zone()

Convenience method returning the local time zone, or UTC if there is no configured local zone.

Warning: Be wary of using local_time_zone(), and particularly so in a server process, as the zone configured for the local machine should be irrelevant. Prefer an explicit zone name.

Returns:

inline CivilSecond to_civil_second(Time t, TimeZone tz)

Helpers for TimeZone::At(Time) to return particularly aligned civil times.

Example:

turbo::Time t = ...;
turbo::TimeZone tz = ...;
const auto cd = turbo::to_civil_day(t, tz);

Parameters:
  • t – the time to convert

  • tz – the time zone to use

Returns:

the converted time

inline CivilMinute to_civil_minute(Time t, TimeZone tz)

similar to to_civil_second()

Parameters:
  • t

  • tz

Returns:

inline CivilHour to_civil_hour(Time t, TimeZone tz)

similar to to_civil_second()

Parameters:
  • t

  • tz

Returns:

inline CivilDay to_civil_day(Time t, TimeZone tz)

similar to to_civil_second()

Parameters:
  • t

  • tz

Returns:

inline CivilMonth to_civil_month(Time t, TimeZone tz)

similar to to_civil_second()

Parameters:
  • t

  • tz

Returns:

inline CivilYear to_civil_year(Time t, TimeZone tz)

similar to to_civil_second()

Parameters:
  • t

  • tz

Returns:

inline Time from_civil(CivilSecond ct, TimeZone tz)

Helper for TimeZone::At(CivilSecond) that provides “order-preserving semantics.

” If the civil time maps to a unique time, that time is returned. If the civil time is repeated in the given time zone, the time using the pre-transition offset is returned. Otherwise, the civil time is skipped in the given time zone, and the transition time is returned. This means that for any two civil times, ct1 and ct2, (ct1 < ct2) => (from_civil(ct1) <= from_civil(ct2)), the equal case being when two non-existent civil times map to the same transition time.

Note: Accepts civil times of any alignment.

Parameters:
  • ct

  • tz

Returns:

inline Time from_date_time(int64_t year, int mon, int day, int hour, int min, int sec, TimeZone tz)

similar to convert_date_time() but returns the “pre” turbo::Time (the unique result, or the instant that is correct using the pre-transition offset (as if the transition never happened)).

Deprecated. Use turbo::from_civil(CivilSecond, TimeZone). Note that the behavior of from_civil() differs from from_date_time() for skipped civil times. If you care about that see turbo::TimeZone::At(turbo::CivilSecond). Example:

turbo::Time t = turbo::from_date_time(2017, 9, 26, 9, 30, 0, lax);
// t = 2017-09-26 09:30:00 -0700

See also

convert_date_time()

Parameters:
  • year

  • mon

  • day

  • hour

  • min

  • sec

  • tz

Returns:

Time from_tm(const struct tm &tm, TimeZone tz)

Converts the given tm_year, tm_mon, tm_mday, tm_hour, tm_min, and tm_sec fields to an turbo::Time using the given time zone.

See ctime(3) for a description of the expected values of the tm fields. If the civil time is unique (see turbo::TimeZone::At(turbo::CivilSecond) above), the matching time instant is returned. Otherwise, the tm_isdst field is consulted to choose between the possible results. For a repeated civil time, tm_isdst != 0 returns the matching DST instant, while tm_isdst == 0 returns the matching non-DST instant. For a skipped civil time there is no matching instant, so tm_isdst != 0 returns the DST instant, and tm_isdst == 0 returns the non-DST instant, that would have matched if the transition never happened. Example:

struct tm tm;
tm.tm_year = 2017 - 1900;
tm.tm_mon = 9 - 1;
tm.tm_mday = 26;
tm.tm_hour = 9;
tm.tm_min = 30;
tm.tm_sec = 0;
tm.tm_isdst = -1;
turbo::Time t = turbo::from_tm(tm, lax);
// t == 2017-09-26 09:30:00 -0700

Parameters:
  • tm

  • tz

Returns:

struct tm to_tm(Time t, TimeZone tz)

Converts the given turbo::Time to a struct tm using the given time zone.

See ctime(3) for a description of the values of the tm fields.

Parameters:
  • t

  • tz

Returns:

std::string format_time(std::string_view format, Time t, TimeZone tz)

Formats the given turbo::Time in the turbo::TimeZone according to the provided format string.

Uses strftime()-like formatting options, with the following extensions:

  • Ez - RFC3339-compatible numeric UTC offset (+hh:mm or -hh:mm)

  • E*z - Full-resolution numeric UTC offset (+hh:mm:ss or -hh:mm:ss)

  • E#S - seconds with # digits of fractional precision

  • E*S - seconds with full fractional precision (a literal ‘*’)

  • E#f - Fractional seconds with # digits of precision

  • E*f - Fractional seconds with full precision (a literal ‘*’)

  • E4Y - Four-character years (-999 … -001, 0000, 0001 … 9999)

  • ET - The RFC3339 “date-time” separator “T” Note that E0S behaves like S, and E0f produces no characters. In contrast E*f always produces at least one digit, which may be ‘0’. Note that Y produces as many characters as it takes to fully render the year. A year outside of [-999:9999] when formatted with E4Y will produce more than four characters, just like Y. We recommend that format strings include the UTC offset (z, Ez, or E*z) so that the result uniquely identifies a time instant. Example:

    turbo::CivilSecond cs(2013, 1, 2, 3, 4, 5);
    turbo::Time t = turbo::from_civil(cs, lax);
    std::string f = turbo::format_time("%H:%M:%S", t, lax);  // "03:04:05"
    f = turbo::format_time("%H:%M:%E3S", t, lax);  // "03:04:05.000"
    
    Note: If the given turbo::Time is turbo::infinite_future(), the returned string will be exactly “infinite-future”. If the given turbo::Time is turbo::infinite_past(), the returned string will be exactly “infinite-past”. In both cases the given format string and turbo::TimeZone are ignored. Example:
    turbo::Time t = turbo::infinite_future();
    std::string f = turbo::format_time("%H:%M:%S", t, lax);  // "infinite-future"
    

Parameters:
  • format

  • t

  • tz

Returns:

bool parse_time(std::string_view format, std::string_view input, Time *time, std::string *err)

Parses an input string according to the provided format string and returns the corresponding turbo::Time.

Uses strftime()-like formatting options, with the same extensions as format_time(), but with the exceptions that E#S is interpreted as E*S, and E#f as E*f. Ez and E*z also accept the same inputs, which (along with z) includes ‘z’ and ‘Z’ as synonyms for +00:00. ET accepts either ‘T’ or ‘t’. Y consumes as many numeric characters as it can, so the matching data should always be terminated with a non-numeric. E4Y always consumes exactly four characters, including any sign. Unspecified fields are taken from the default date and time of … “1970-01-01 00:00:00.0 +0000” For example, parsing a string of “15:45” (H:M) will return an turbo::Time that represents “1970-01-01 15:45:00.0 +0000”. Note that since parse_time() returns time instants, it makes the most sense to parse fully-specified date/time strings that include a UTC offset (z, Ez, or E*z). Note also that turbo::parse_time() only heeds the fields year, month, day, hour, minute, (fractional) second, and UTC offset. Other fields, like weekday (a or A), while parsed for syntactic validity, are ignored in the conversion. Date and time fields that are out-of-range will be treated as errors rather than normalizing them like turbo::CivilSecond does. For example, it is an error to parse the date “Oct 32, 2013” because 32 is out of range. A leap second of “:60” is normalized to “:00” of the following minute with fractional seconds discarded. The following table shows how the given seconds and subseconds will be parsed: “59.x” -> 59.x // exact “60.x” -> 00.0 // normalized “00.x” -> 00.x // exact Errors are indicated by returning false and assigning an error message to the “err” out param if it is non-null. Note: If the input string is exactly “infinite-future”, the returned turbo::Time will be turbo::infinite_future() and true will be returned. If the input string is “infinite-past”, the returned turbo::Time will be turbo::infinite_past() and true will be returned.

Parameters:
  • format

  • input

  • time

  • err

Returns:

bool parse_time(std::string_view format, std::string_view input, TimeZone tz, Time *time, std::string *err)

Like parse_time() above, but if the format string does not contain a UTC offset specification (z/Ez/E*z) then the input is interpreted in the given TimeZone.

This means that the input, by itself, does not identify a unique instant. Being time-zone dependent, it also admits the possibility of ambiguity or non-existence, in which case the “pre” time (as defined by TimeZone::TimeInfo) is returned. For these reasons we recommend that all date/time strings include a UTC offset so they’re context independent. Example:

turbo::Time t;
std::string err;
bool b = turbo::parse_time("%Y-%m-%d %H:%M:%S", "2013-10-19 12:34:56",
                           lax, &t, &err);
// b == true && err.empty() && t == 2013-10-19 12:34:56 -0700

Parameters:
  • format

  • input

  • tz

  • time

  • err

Returns:

class TimeZone
#include <time.h>

The turbo::TimeZone is an opaque, small, value-type class representing a geo-political region within which particular rules are used for converting between absolute and civil times (see https://git.io/v59Ly).

turbo::TimeZone values are named using the TZ identifiers from the IANA Time Zone Database, such as “America/Los_Angeles” or “Australia/Sydney”. turbo::TimeZone values are created from factory functions such as turbo::load_time_zone(). Note: strings like “PST” and “EDT” are not valid TZ identifiers. Prefer to pass by value rather than const reference.

For more on the fundamental concepts of time zones, absolute times, and civil times, see https://github.com/google/cctz#fundamental-concepts

Examples:

turbo::TimeZone utc = turbo::utc_time_zone();
turbo::TimeZone pst = turbo::fixed_time_zone(-8 * 60 * 60);
turbo::TimeZone loc = turbo::local_time_zone();
turbo::TimeZone lax;
if (!turbo::load_time_zone("America/Los_Angeles", &lax)) {
      // handle error case
}
See also:

Public Functions

CivilInfo At(Time t) const

Returns the civil time for this TimeZone at a certain turbo::Time.

If the input time is infinite, the output civil second will be set to CivilSecond::max() or min(), and the subsecond will be infinite.

Example:

const auto epoch = lax.At(turbo::unix_epoch());
// epoch.cs == 1969-12-31 16:00:00
// epoch.subsecond == turbo::zero_duration()
// epoch.offset == -28800
// epoch.is_dst == false
// epoch.abbr == "PST"

Parameters:

t – the time to convert

Returns:

the converted time

TimeInfo At(CivilSecond ct) const

Returns the absolute time(s) for this TimeZone at a certain turbo::CivilSecond.

When the civil time is skipped or repeated, returns times calculated using the pre-transition and post-transition UTC offsets, plus the transition time itself.

Examples:

const auto jan01 = lax.At(turbo::CivilSecond(2011, 1, 1, 0, 0, 0));
// jan01.kind == TimeZone::TimeInfo::UNIQUE
// jan01.pre    is 2011-01-01 00:00:00 -0800
// jan01.trans  is 2011-01-01 00:00:00 -0800
// jan01.post   is 2011-01-01 00:00:00 -0800

// A Spring DST transition, when there is a gap in civil time
const auto mar13 = lax.At(turbo::CivilSecond(2011, 3, 13, 2, 15, 0));
// mar13.kind == TimeZone::TimeInfo::SKIPPED
// mar13.pre   is 2011-03-13 03:15:00 -0700
// mar13.trans is 2011-03-13 03:00:00 -0700
// mar13.post  is 2011-03-13 01:15:00 -0800

// A Fall DST transition, when civil times are repeated
const auto nov06 = lax.At(turbo::CivilSecond(2011, 11, 6, 1, 15, 0));
// nov06.kind == TimeZone::TimeInfo::REPEATED
// nov06.pre   is 2011-11-06 01:15:00 -0700
// nov06.trans is 2011-11-06 01:00:00 -0800
// nov06.post  is 2011-11-06 01:15:00 -0800

Parameters:

cs – the civil time to convert

Returns:

the converted time

struct CivilInfo
struct CivilTransition
#include <time.h>

Finds the time of the next offset change in this time zone.

By definition, NextTransition(t, &trans) returns false when t is infinite_future(). If the zone has no transitions, the result will also be false no matter what the argument.

Otherwise, when t is infinite_past(), NextTransition(t, &trans) returns true and sets trans to the first recorded transition. Chains of calls to NextTransition()/PrevTransition() will eventually return false, but it is unspecified exactly when NextTransition(t, &trans) jumps to false, or what time is set by PrevTransition(t, &trans) for a very distant t.

Note

Enumeration of time-zone transitions is for informational purposes only. Modern time-related code should not care about when offset changes occur. Example:

turbo::TimeZone nyc;
if (!turbo::load_time_zone("America/New_York", &nyc)) { ... }
const auto now = turbo::time_now();
auto t = turbo::infinite_past();
turbo::TimeZone::CivilTransition trans;
while (t <= now && nyc.NextTransition(t, &trans)) {
    // transition: trans.from -> trans.to
    t = nyc.At(trans.to).trans;
}

struct TimeInfo
#include <time.h>

Information about the absolute times corresponding to a civil time.

(Subseconds must be handled separately.)

It is possible for a caller to pass a civil-time value that does not represent an actual or unique instant in time (due to a shift in UTC offset in the TimeZone, which results in a discontinuity in the civil-time components). For example, a daylight-saving-time transition skips or repeats civil times&#8212;in the United States, March 13, 2011 02:15 never occurred, while November 6, 2011 01:15 occurred twice&#8212;so requests for such times are not well-defined. To account for these possibilities, turbo::TimeZone::TimeInfo is richer than just a single turbo::Time.