Code Monkey home page Code Monkey logo

cctz's Introduction

This is not an official Google product.

Overview

CCTZ contains two libraries that cooperate with <chrono> to give C++ programmers all the necessary tools for computing with dates, times, and time zones in a simple and correct manner. The libraries in CCTZ are:

  • The Civil-Time Library — This is a header-only library that supports computing with human-scale time, such as dates (which are represented by the cctz::civil_day class). This library is declared in include/cctz/civil_time.h.
  • The Time-Zone Library — This library uses the IANA time zone database that is installed on the system to convert between absolute time and civil time. This library is declared in include/cctz/time_zone.h.

These libraries are currently known to work on Linux, Mac OS X, and Android.

They will also work on Windows if you install the zoneinfo files. We are interested, though, in an implementation of the cctz::TimeZoneIf interface that calls the Windows time APIs instead. Please contact us if you're interested in contributing.

Getting Started

CCTZ is best built and tested using the Bazel build system and the Google Test framework. (There is also a simple Makefile and a CMakeLists.txt that should work if you're unable to use Bazel.)

  1. Download/install Bazel
  2. Get the cctz source: git clone https://github.com/google/cctz.git then cd cctz
  3. Build cctz and run the tests: bazel test :all

With CMake:

  1. Make sure you have CMake >= 2.8.12 installed.

  2. Get the cctz source: git clone https://github.com/google/cctz.git then cd cctz.

  3. Build cctz so that is can be used by shared libraries and run the tests (use -DBUILD_TESTING=OFF to skip the tests):

    mkdir mybuild
    cd mybuild
    cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON ..
    cmake --build . --config Release
    ctest
    cmake --build . --config Release --target install
    
  4. Use in your CMake-based project with:

    find_package(cctz REQUIRED)
    add_executable(mytarget file.cc)
    target_link_libraries(mytarget cctz::cctz)

Note: When using CCTZ in your own project, you might find it easiest to compile the sources using your existing build system.

Next Steps:

  1. See the documentation for the libraries in CCTZ:
  2. Look at the examples in https://github.com/google/cctz/tree/master/examples
  3. Join our mailing list to ask questions and keep informed of changes:

Fundamental Concepts

[The concepts presented here describe general truths about the problem domain and are library and language agnostic. An understanding of these concepts helps the programmer correctly reason about even the most-complicated time-programming challenges and produce the simplest possible solutions.]

There are two main ways to think about time in a computer program: as absolute time, and as civil time. Both have their uses and it is important to understand when each is appropriate. Absolute and civil times may be converted back and forth using a time zone — this is the only way to correctly convert between them. Let us now look more deeply at the three main concepts of time programming: Absolute Time, Civil Time, and Time Zone.

Absolute time uniquely and universally represents a specific instant in time. It has no notion of calendars, or dates, or times of day. Instead, it is a measure of the passage of real time, typically as a simple count of ticks since some epoch. Absolute times are independent of all time zones and do not suffer from human-imposed complexities such as daylight-saving time (DST). Many C++ types exist to represent absolute times, classically time_t and more recently std::chrono::time_point.

Civil time is the legally recognized representation of time for ordinary affairs (cf. https://www.merriam-webster.com/dictionary/civil). It is a human-scale representation of time that consists of the six fields — year, month, day, hour, minute, and second (sometimes shortened to "YMDHMS") — and it follows the rules of the Proleptic Gregorian Calendar, with 24-hour days divided into 60-minute hours and 60-second minutes. Like absolute times, civil times are also independent of all time zones and their related complexities (e.g., DST). While std::tm contains the six civil-time fields (YMDHMS), plus a few more, it does not have behavior to enforce the rules of civil time.

Time zones are geo-political regions within which human-defined rules are shared to convert between the absolute-time and civil-time domains. A time zone's rules include things like the region's offset from the UTC time standard, daylight-saving adjustments, and short abbreviation strings. Time zones often have a history of disparate rules that apply only for certain periods, because the rules may change at the whim of a region's local government. For this reason, time-zone rules are usually compiled into data snapshots that are used at runtime to perform conversions between absolute and civil times. There is currently no C++ standard library supporting arbitrary time zones.

In order for programmers to reason about and program applications that correctly deal with these concepts, they must have a library that correctly implements the above concepts. CCTZ adds to the existing C++11 <chrono> library to fully implement the above concepts.

  • Absolute time — This is implemented by the existing C++11 <chrono> library without modification. For example, an absolute point in time is represented by a std::chrono::time_point.
  • Civil time — This is implemented by the include/cctz/civil_time.h library that is provided as part of CCTZ. For example, a "date" is represented by a cctz::civil_day.
  • Time zone — This is implemented by the include/cctz/time_zone.h library that is provided as part of CCTZ. For example, a time zone is represented by an instance of the class cctz::time_zone.

Examples

Hello February 2016

This "hello world" example uses a for-loop to iterate the days from the first of February until the month of March. Each day is streamed to output, and if the day happens to be the 29th, we also output the day of the week.

#include <iostream>
#include "cctz/civil_time.h"

int main() {
  for (cctz::civil_day d(2016, 2, 1); d < cctz::civil_month(2016, 3); ++d) {
    std::cout << "Hello " << d;
    if (d.day() == 29) {
      std::cout << " <- leap day is a " << cctz::get_weekday(d);
    }
    std::cout << "\n";
  }
}

The output of the above program is

Hello 2016-02-01
Hello 2016-02-02
Hello 2016-02-03
[...]
Hello 2016-02-27
Hello 2016-02-28
Hello 2016-02-29 <- leap day is a Monday

One giant leap

This example shows how to use all three libraries (<chrono>, civil time, and time zone) together. In this example, we know that viewers in New York watched Neil Armstrong's first walk on the moon on July 20, 1969 at 10:56 PM. But we'd like to see what time it was for our friend watching in Sydney, Australia.

#include <iostream>
#include "cctz/civil_time.h"
#include "cctz/time_zone.h"

int main() {
  cctz::time_zone nyc;
  cctz::load_time_zone("America/New_York", &nyc);

  // Converts the input civil time in NYC to an absolute time.
  const auto moon_walk =
    cctz::convert(cctz::civil_second(1969, 7, 20, 22, 56, 0), nyc);

  std::cout << "Moon walk in NYC: "
            << cctz::format("%Y-%m-%d %H:%M:%S %Ez\n", moon_walk, nyc);

  cctz::time_zone syd;
  if (!cctz::load_time_zone("Australia/Sydney", &syd)) return -1;
  std::cout << "Moon walk in SYD: "
            << cctz::format("%Y-%m-%d %H:%M:%S %Ez\n", moon_walk, syd);
}

The output of the above program is

Moon walk in NYC: 1969-07-20 22:56:00 -04:00
Moon walk in SYD: 1969-07-21 12:56:00 +10:00

This example shows that the absolute time (the std::chrono::time_point) of the first walk on the moon is the same no matter the time zone of the viewer (the same time point is used in both calls to format()). The only difference is the time zone in which the moon_walk time point is rendered. And in this case we can see that our friend in Sydney was probably eating lunch while watching that historic event.

References

cctz's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cctz's Issues

Missing CMake install rules

Currently cctz doesn't provide CMake install rule which is a pain for CMake users to integrate it.

On the same subject:

Linux <-> OSX mismatch (internal overflow?)

Hi, this small test program gives different results on OS X vs. Linux (both gcc-6.1.1 and llvm-clang++-3.6):

#include <chrono>
#include <iostream>
#include <time_zone.h>

int main (int argc, char ** argv) {
    std::chrono::system_clock::time_point tp;
    auto date = "18 April 2275";
    cctz::parse("%d %B %Y", date, cctz::local_time_zone(), &tp);
    auto d = cctz::convert(tp, cctz::local_time_zone());
    std::cout << date << " <-> " << d << std::endl;
    return 0;
}

// output OSX/64bit:   18 April 2275 <-> 2275-04-18T00:00:00
// output Linux/64bit: 18 April 2275 <-> 1690-09-26T23:18:55

The bug is exposed when verifying the Australian Astronomical Society Easter Dates against Knuth's Easter Date algorithm.

warning: missing field initializer

When compiling thus

clang++ -ggdb3 -Wall -Wextra -std=c++14  -c -fpic -o cctz_fmt.o cctz_fmt.cc

I see warnings at lines 31, 482, and 637 about a missing field tm_min.

warning: missing field 'tm_min' initializer [-Wmissing-field-initializers]

Similarly, clang++ complains of type_index missing at 808 of cctz_info.cc.

Perhaps an old-fashioned memset(&tm, 0, sizeof(tm)) would be better?

Use zone.tab instead of files directly in /usr/share/zoneinfo

As per
http://unix.stackexchange.com/questions/35781/why-is-zone-tab-missing-so-many-time-zones
and
http://postgresql.nabble.com/A-renewed-plea-for-inclusion-of-zone-tab-td2005687.html
and
https://issues.cloudera.org/browse/IMPALA-3316
often there are subset of files in /usr/share/zoneinfo,
while /usr/share/zoneinfo/zone.tab always has complete information.

It would be more reliable to use Use zone.tab instead of files directly in /usr/share/zoneinfo/zone.tab instead of individual files?

The bazel dependency is maybe excessive

I have an ongoing conversation with the bazel folks about getting bazel to work well enough that I can use cctz.

Since that conversation still ongoing, I wrote a quick makefile that makes libcctz.a and runs its tests. To be truly useful, it should probably be a cmakefile, but I'm happy to contribute my simple makefile in case that can help.

I understand if you don't want to go in that direction, and what I've done isn't overly complicated for others to redo as needed. It was faster than bringing up bazel just to compile cctz, though.

parse(civil_second)

Hi,

There are cases where first parsing a std::chrono time point and then converting it to cctz::civil_second is cumbersome.

As an example, when parsing the time of day "07:30:12.123" for a calendar, or a recurring event, it is currently required to first parse the absolute time and then try to get rid of the date offset, and time zone shift.

A quick glance in cctz.git/src/time_zone_format.cc suggests that parse() generates a civil_second anyway, before converting to an absolute time.

Might it make sense to expose this to the API, for example by splitting cctz::parse() in two functions? Conceptually, like this:

     bool cctz::parse (const std::string& format, const std::string& input,
           const time_zone& tz, cctz::civil_second* cs,
           std::chrono::nanoseconds* ns) {
        /* Mostly the current implementation in cctz.git/src/time_zone_format.cc,
         * but returning cs and _not_ calling ptz.lookup().
         */
    }

     bool cctz::parse (const std::string& format, const std::string& input,
           const time_zone& tz, time_point<sys_seconds>* sec,
           std::chrono::nanoseconds* ns) {
        cctz::civil_second cs;
        bool retval = cctz::parse(format, input, tz, &cs, ns);
        *sec = cctz::convert(cs, tz);
        return retval;
    }

What do you think?

cmake failed when turning BUILD_TESTING option ON

I built cctz with cmake with BUILD_TESTING option ON and
it didn't work because it didn't find the benchmark package. I checked the CMakeLists.txt, it called
find_package(benchmark) and there isn't a cmake module to find such package. And I think there is no
such native cmake module. So shall we add a Findbenchmark.cmake under cmake/module path? And
the getting started part of readme doc didn't mention about benchmark, I think it should also be installed
in advance. So I think maybe the readme doc should be modified to mention about it.

Makefile install rule broke in commit 5c54e2a1da81d6def6a720df16b8570341a5a90a

This commit

https://github.com/google/cctz/commit/2e83ff2e47dab211eedf4daa508c34b52cdcc7af

introduced calls to command cp with the '-d' flag in several install targets, this is a GNU extension not supported on non-GNU POSIX systems (e.g. OS X and BSD). A portable solution might use the 'install' command (non-POSIX but available on both BSD and GNU systems) to create directories and copy files, or restrict 'cp' usage to the POSIX option subset?

g++-4.9 -pedantic and __int128

I am considering wrappnig this for use by R. The CRAN maintainers are pretty strict about compiler warnings, and the code in your repo currently leads to two screen fulls of

In file included from ../inst/include/src/cctz_impl.h:23:0,
                 from cctz_cnv.cc:20:
../inst/include/src/cctz_info.h:46:12: warning: ISO C++ does not support ‘__int128’ for ‘offset’ [-Wpedantic]
   __int128 offset;  // seconds from some epoch DateTime
            ^
../inst/include/src/cctz_info.h:57:67: warning: ISO C++ does not support ‘__int128’ for ‘operator-’ [-Wpedantic]
 inline __int128 operator-(const DateTime& lhs, const DateTime& rhs) {
                                                                   ^
../inst/include/src/cctz_info.h:126:59: warning: ISO C++ does not support ‘__int128’ for ‘offset’ [-Wpedantic]
                      int hour, int min, int sec, __int128 offset) const;
                                                           ^

I didn't see an obvious way to accommodate this during build-time. Would you consider addressing it in source?

Don't load utc in map when TimeZoneInfo::Load failed

If some file from tzdata cannot be opened, utc time zone will loading to map. It can be problem. For example, if TZDIR has incorrect value and we change it, other (correct) rules of time zone don't loading.
Also Asia/Tehran: Failed to parse 'IRST-3:30IRDT,J80/0,J264/0' message isn't clear for me. It means that the time zone was incorrect loading?

Valgrind 3.10 memory check failures

Our valgrind 3.10 checks showed that cctz allocates some memory that it does not free. Interestingly, valgrind 3.11 does not complain about this.

Here is a simple program to demonstrate the issue:

#include <src/cctz.h>

int main(int argc, char** argv)
{
    cctz::TimeZone tokyo;
    LoadTimeZone("Asia/Tokyo", &tokyo);
    return 0;
}

The corresponding output from valgrind 3.10 is as follows:

valgrind --error-exitcode=1 --leak-check=full --num-callers=50 --error-limit=no --track-origins=yes cctz_test
==17915== Memcheck, a memory error detector
==17915== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==17915== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==17915== Command: cctz_test
==17915==
==17915==
==17915== HEAP SUMMARY:
==17915==     in use at exit: 984 bytes in 16 blocks
==17915==   total heap usage: 47 allocs, 31 frees, 2,568 bytes allocated
==17915==
==17915== 28 bytes in 1 blocks are possibly lost in loss record 4 of 16
==17915==    at 0x4A09033: operator new(unsigned long) (vg_replace_malloc.c:324)
==17915==    by 0x4CEA378: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEBD64: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEBE42: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x40F19D: cctz::UTCTimeZone() (cctz_cnv.cc:26)
==17915==    by 0x40F50C: cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1}::operator()() const (cctz_impl.cc:39)
==17915==    by 0x40FCB9: void std::_Bind_simple<cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1} ()>::_M_invoke<>(std::_Index_tuple<>) (functional:1598)
==17915==    by 0x40FC50: std::_Bind_simple<cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1} ()>::operator()() (functional:1586)
==17915==    by 0x40FB7B: void std::__once_call_impl<std::_Bind_simple<cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1} ()> >() (mutex:787)
==17915==    by 0x3E5840C112: pthread_once (in /lib64/libpthread-2.5.so)
==17915==    by 0x40F494: __gthread_once(int*, void (*)()) (gthr-default.h:718)
==17915==    by 0x40FB0A: void std::call_once<cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1}>(std::once_flag&, cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1}&&) (mutex:819)
==17915==    by 0x40F527: cctz::(anonymous namespace)::LoadUTCTimeZone() (cctz_impl.cc:39)
==17915==    by 0x40F782: cctz::TimeZone::Impl::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_impl.cc:74)
==17915==    by 0x40F363: cctz::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_cnv.cc:45)
==17915==    by 0x40F117: main (main.cc:6)
==17915==
==17915== 31 bytes in 1 blocks are possibly lost in loss record 5 of 16
==17915==    at 0x4A09033: operator new(unsigned long) (vg_replace_malloc.c:324)
==17915==    by 0x4CEA378: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEB0E7: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEB1CF: std::string::reserve(unsigned long) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEB310: std::string::append(unsigned long, char) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x414009: cctz::TimeZoneInfo::ResetToBuiltinUTC(int) (cctz_info.cc:367)
==17915==    by 0x41538D: cctz::TimeZoneInfo::Load(std::string const&) (cctz_info.cc:628)
==17915==    by 0x411885: cctz::TimeZoneIf::Load(std::string const&) (cctz_if.cc:31)
==17915==    by 0x40F825: cctz::TimeZone::Impl::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_impl.cc:85)
==17915==    by 0x40F363: cctz::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_cnv.cc:45)
==17915==    by 0x40F1B0: cctz::UTCTimeZone() (cctz_cnv.cc:26)
==17915==    by 0x40F50C: cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1}::operator()() const (cctz_impl.cc:39)
==17915==    by 0x40FCB9: void std::_Bind_simple<cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1} ()>::_M_invoke<>(std::_Index_tuple<>) (functional:1598)
==17915==    by 0x40FC50: std::_Bind_simple<cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1} ()>::operator()() (functional:1586)
==17915==    by 0x40FB7B: void std::__once_call_impl<std::_Bind_simple<cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1} ()> >() (mutex:787)
==17915==    by 0x3E5840C112: pthread_once (in /lib64/libpthread-2.5.so)
==17915==    by 0x40F494: __gthread_once(int*, void (*)()) (gthr-default.h:718)
==17915==    by 0x40FB0A: void std::call_once<cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1}>(std::once_flag&, cctz::(anonymous namespace)::LoadUTCTimeZone()::{lambda()#1}&&) (mutex:819)
==17915==    by 0x40F527: cctz::(anonymous namespace)::LoadUTCTimeZone() (cctz_impl.cc:39)
==17915==    by 0x40F782: cctz::TimeZone::Impl::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_impl.cc:74)
==17915==    by 0x40F363: cctz::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_cnv.cc:45)
==17915==    by 0x40F117: main (main.cc:6)
==17915==
==17915== 33 bytes in 1 blocks are possibly lost in loss record 7 of 16
==17915==    at 0x4A09033: operator new(unsigned long) (vg_replace_malloc.c:324)
==17915==    by 0x4CEA378: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEB0E7: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEB1CF: std::string::reserve(unsigned long) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEB24B: std::string::push_back(char) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x414A34: cctz::TimeZoneInfo::Load(std::string const&, _IO_FILE*) (cctz_info.cc:523)
==17915==    by 0x4154E3: cctz::TimeZoneInfo::Load(std::string const&) (cctz_info.cc:649)
==17915==    by 0x411885: cctz::TimeZoneIf::Load(std::string const&) (cctz_if.cc:31)
==17915==    by 0x40F825: cctz::TimeZone::Impl::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_impl.cc:85)
==17915==    by 0x40F363: cctz::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_cnv.cc:45)
==17915==    by 0x40F117: main (main.cc:6)
==17915==
==17915== 35 bytes in 1 blocks are possibly lost in loss record 8 of 16
==17915==    at 0x4A09033: operator new(unsigned long) (vg_replace_malloc.c:324)
==17915==    by 0x4CEA378: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEBD64: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEBE42: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x40F104: main (main.cc:6)
==17915==
==17915== 41 bytes in 1 blocks are possibly lost in loss record 10 of 16
==17915==    at 0x4A09033: operator new(unsigned long) (vg_replace_malloc.c:324)
==17915==    by 0x4CEA378: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEA572: std::string::_M_mutate(unsigned long, unsigned long, unsigned long) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x4CEA70B: std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) (in /opt/optiver/gcc/4.7.2/lib64/libstdc++.so.6.0.17)
==17915==    by 0x41497B: cctz::TimeZoneInfo::Load(std::string const&, _IO_FILE*) (cctz_info.cc:503)
==17915==    by 0x4154E3: cctz::TimeZoneInfo::Load(std::string const&) (cctz_info.cc:649)
==17915==    by 0x411885: cctz::TimeZoneIf::Load(std::string const&) (cctz_if.cc:31)
==17915==    by 0x40F825: cctz::TimeZone::Impl::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_impl.cc:85)
==17915==    by 0x40F363: cctz::LoadTimeZone(std::string const&, cctz::TimeZone*) (cctz_cnv.cc:45)
==17915==    by 0x40F117: main (main.cc:6)
==17915==
==17915== LEAK SUMMARY:
==17915==    definitely lost: 0 bytes in 0 blocks
==17915==    indirectly lost: 0 bytes in 0 blocks
==17915==      possibly lost: 168 bytes in 5 blocks
==17915==    still reachable: 816 bytes in 11 blocks
==17915==         suppressed: 0 bytes in 0 blocks
==17915== Reachable blocks (those to which a pointer was found) are not shown.
==17915== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==17915==
==17915== For counts of detected and suppressed errors, rerun with: -v
==17915== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 4 from 4)

The issue seems to be with the time_zone_map object (and the TimeZone::Impl objects stored in it). I can see why you would not want to automatically release this map (used in dynamically loaded libraries; non-deterministic de-initialization order), but maybe cctz could provide a Terminate()/Uninitialize()/Cleanup() function that could be called explicitly when we know it is safe to do so?

Clang static analyzer report

Hi,

the clang static analyzer (scan-build) reports a minor issue in cctz.git/src/time_zone_info.cc:

622	  // Copy all the abbreviations.
623	  abbreviations_.assign(bp, hdr.charcnt);
624	  bp += hdr.charcnt;
625	 
626	  // Skip the unused portions. We've already dispensed with leap-second
627	  // encoded zoneinfo. The ttisstd/ttisgmt indicators only apply when
628	  // interpreting a POSIX spec that does not include start/end rules, and
629	  // that isn't the case here (see "zic -p").
630	  bp += (8 + 4) * hdr.leapcnt;  // leap-time + TAI-UTC
631	  bp += 1 * hdr.ttisstdcnt;     // UTC/local indicators
632	  bp += 1 * hdr.ttisgmtcnt;     // standard/wall indicators
Value stored to 'bp' is never read

Indeed, this last modification of pointer bp seems to be dead code. Maybe some unintentional left-over from earlier reorganization?

add microseconds support

I guess it's not really 'civil' to deal with microseconds but it could be interesting to add precision to the civil_time objects by adding a microseconds attribute.

warning: unused parameter 'zone' [-Wunused-parameter]

When compiling tools/time_tool.cc, I see this warning:

time_tool.cc:58:65: warning: unused parameter 'zone' [-Wunused-parameter]

If it is intentional not to use zone, perhaps a statement like this would at least be helpful?

(void)zone;   // Unused for now, silence compiler warning.

Make tzdir a parameter to TimeZoneInfo::Load?

This would be useful for R as R bundles it's own zoneinfo db on windows. I think it's a bit more elegant as an explicit parameter, rather relying on a global variable.

(But it's not clear to me how that would interact with localtime)

cmake windows shared builds do not export symbols

When building shared libs on windows, using cmake and -DBUILD_SHARED_LIBS=On, no .lib file is produced, which in turn doesn't allow a consumer to link against cctz.

Ideally, symbols should be properly exported (see https://msdn.microsoft.com/en-us/library/a90k134d.aspx), then a lib file will be generated.

A not-so-elegant, but working solution may be to enable: CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS, which I had success with, however for optimal results you should only export what should be exported.

This workaround is as simple as adding:

set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS YES CACHE BOOL "Export all symbols")

or running the cmake config command with -DCMAKE_WINDOWS_EXPORT_ALL_SYMBOLS=True

thanks.

console debug output on OSX

Without having investigated this further, I'd like to report that on OS X 10.10.5 cctz emits some debug output to the console:

localtime: Missing POSIX spec
EST5EDT: Missing POSIX spec

(Time zone and conversion results seem correct, though)
On linux, this is not happening.

Not really an issue

Just wondering how I could contribute to your project, I have been programming for quite some time, but I am kinda new to github.

Will the precompiled tz data files be updated if new ones are available?

Hi there,

in your forum https://groups.google.com/forum/#!forum/cctz Bradley White wrote on 26. October 2017:
"Update: We have now included pre-compiled zoneinfo files in the CCTZ distribution, so Windows users should just be able to copy those."

Well done, thank you very much! This is a big help for all Windows users.

New timezone data files are updated once or twice a year these days. The last update 'tzdata2018b' happened on 17. January 2018 at https://www.iana.org/time-zones.

If new time zone data files are available, will cctz update their precompiled timezone data files also (located in its archive file 'cctz-master.zip' under \testdata\zoneinfo)?

How to check which version of the precompiled time zone data files are included in the cctz archive file? Is there a readme file for this or any other way to check it?

If there is no way to check the version of the included precompiled tz data files yet, it would be great if this feature could be added to cctz.

Best regards,
mireiner

Build errors on FreeBSD

I am an indirect user of CCTZ via RcppCCTZ, a package for R. My OS is FreeBSD, on which I had problems, when I tried to build the R package RcppCCTZ.

It turns out, that both build errors occur inside the original code of the CCTZ projekt. The first error is in time_zone_info.cc and looks like:

g++49 -std=gnu++11 -I/usr/local/lib/R/include -DNDEBUG  -I"/usr/local/lib/R/library/Rcpp/include" -DLIBICONV_PLUG -I/usr/local/include -isystem /usr/local/include  -I../inst/include -fpic  -O2 -pipe -DLIBICONV_PLUG -fstack-protector -Wl,-rpath=/usr/local/lib/gcc49 -isystem /usr/local/include -fno-strict-aliasing  -DLIBICONV_PLUG -Wl,-rpath=/usr/local/lib/gcc49 -isystem /usr/local/include -c time_zone_info.cc -o time_zone_info.o
time_zone_info.cc: In function 'char* cctz::{anonymous}::errmsg(int, char*, size_t)':
time_zone_info.cc:64:40: error: invalid conversion from 'int' to 'char*' [-fpermissive]
   return strerror_r(errnum, buf, buflen);
                                        ^

The second error comes from time_zone_libc.cc:

g++49 -std=gnu++11 -I/usr/local/lib/R/include -DNDEBUG  -I"/usr/local/lib/R/library/Rcpp/include" -DLIBICONV_PLUG -I/usr/local/include -isystem /usr/local/include  -I../inst/include -fpic  -O2 -pipe -DLIBICONV_PLUG -fstack-protector -Wl,-rpath=/usr/local/lib/gcc49 -isystem /usr/local/include -fno-strict-aliasing  -DLIBICONV_PLUG -Wl,-rpath=/usr/local/lib/gcc49 -isystem /usr/local/include -c time_zone_libc.cc -o time_zone_libc.o
time_zone_libc.cc: In member function 'virtual cctz::time_zone::absolute_lookup cctz::TimeZoneLibC::BreakTime(cctz::time_point<std::chrono::duration<long int> >&) const':
time_zone_libc.cc:55:65: warning: pointer to a function used in arithmetic [-Wpointer-arith]
 # define OFFSET(tm) (timezone + ((tm).tm_isdst > 0 ? 60 * 60 : 0))
                                                                 ^
time_zone_libc.cc:81:17: note: in expansion of macro 'OFFSET'
     al.offset = OFFSET(tm);
                 ^
time_zone_libc.cc:55:31: error: invalid conversion from 'char* (*)(int, int)' to 'int' [-fpermissive]
 # define OFFSET(tm) (timezone + ((tm).tm_isdst > 0 ? 60 * 60 : 0))
                               ^
time_zone_libc.cc:81:17: note: in expansion of macro 'OFFSET'
     al.offset = OFFSET(tm);
                 ^

After explicitely adding an 'if def()' for FreeBSD within time_zone_info.cc and time_zone_libc.cc, both files show no errors or warnings anymore in the build. Because FreeBSD compiler suite in many issues is very near to Apple's, I decided to put the 'if def()' beside the 'Apple case'. The patches are simple:

--- src/time_zone_info.cc.orig	2017-02-04 17:15:43.000000000 +0100
+++ src/time_zone_info.cc	2017-02-07 08:39:53.108867000 +0100
@@ -54,7 +54,7 @@
 #if defined(_MSC_VER) || defined(WIN32) || defined(__WIN32) ||
defined(__WIN32__)
   strerror_s(buf, buflen, errnum);
   return buf;
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) || defined(__FreeBSD__)
   strerror_r(errnum, buf, buflen);
   return buf;
 #elif (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE
--- src/time_zone_libc.cc.orig	2017-02-04 17:15:43.000000000 +0100
+++ src/time_zone_libc.cc	2017-02-07 08:47:40.103646000 +0100
@@ -28,7 +28,7 @@
 #  define OFFSET(tm) ((tm).__tm_gmtoff)
 #  define ABBR(tm)   ((tm).__tm_zone)
 # endif
-#elif defined(__APPLE__)
+#elif defined(__APPLE__) || defined(__FreeBSD__)
 # define OFFSET(tm) ((tm).tm_gmtoff)
 # define ABBR(tm)   ((tm).tm_zone)
 #elif defined(__sun)

For some reason, the already existing symbol __USE_BSD obviously is not triggered by the presence of FreeBSD. I looked into the symbols of my compiler GCC-4.9.4 with

: | gcc -dM -E -x c - | less

and only found

#define __FreeBSD__ 12

Because CLANG also uses this symbol on FreeBSD, it is also valid for the case, that FreeBSD users decide to use CLANG instead of GCC to build RcppCCTZ respectively CCTZ.

If these two patches look fine in your eyes, it would be nice, if you would integrate them into your sources. Many thanks in advance.

tzdata files on OS X are old format

The zoneinfo files installed in /usr/share/zoneinfo on my Mac (10.10.5) contain current data (tzdata 2015d), but the zoneinfo data's file format is very old.

$ file /usr/share/zoneinfo/America/New_York
/usr/share/zoneinfo/America/New_York: timezone data, old version, 4 gmt time flags, 4 std time flags, no leap seconds, 235 transition times, 4 abbreviation chars

This shows that the zone info file was likely compiled with an old zic.

$ zic --version
zic: @(#)zic.c  7.116

Which I believe is circa 2007 (http://www.opensource.apple.com/source/system_cmds/system_cmds-643.30.1/zic.tproj/).

What's needed?

To make cctz work on OS X we need one of:

  • Apple to update their zic and the format of their zoneinfo files
  • cctz could learn how to handle old zoneinfo files

Abbreviated time zones?

A range of common abbreviated(?) timezones are not found on my machine (notably CET, EST). What is the recommended way to deal with those? Is there a conversion table somewhere that I can use?

Thanks.

GCC 5 fails compilation

I have successfully compiled cctz on gcc6 and 7, but when I try to compile it with cmake using gcc v5.4.1 (on ubuntu/linux):

cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DBUILD_TESTING=OFF -DCMAKE_CXX_STANDARD=11 ..
cmake --build . --config Release
...
..
[ 37%] Building CXX object CMakeFiles/cctz.dir/src/zone_info_source.cc.o
[ 40%] Linking CXX static library libcctz.a
[ 40%] Built target cctz
Scanning dependencies of target time_tool
[ 44%] Building CXX object CMakeFiles/time_tool.dir/src/time_tool.cc.o
/home/sigmoidal/opensource/cctz/src/time_tool.cc: In function ‘bool ParseYearRange(bool, const string&, cctz::year_t*, cctz::year_t*)’:
/home/sigmoidal/opensource/cctz/src/time_tool.cc:253:30: error: ‘stoll’ is not a member of ‘std’
   const cctz::year_t first = std::stoll(args, &pos);
                              ^
/home/sigmoidal/opensource/cctz/src/time_tool.cc:268:31: error: ‘stoll’ is not a member of ‘std’
   const cctz::year_t second = std::stoll(rem, &pos);
                               ^
/home/sigmoidal/opensource/cctz/src/time_tool.cc: In function ‘int main(int, char**)’:
/home/sigmoidal/opensource/cctz/src/time_tool.cc:390:24: error: ‘stoll’ is not a member of ‘std’
       const time_t t = std::stoll(spec, &end);
                        ^
CMakeFiles/time_tool.dir/build.make:62: recipe for target 'CMakeFiles/time_tool.dir/src/time_tool.cc.o' failed
make[2]: *** [CMakeFiles/time_tool.dir/src/time_tool.cc.o] Error 1
CMakeFiles/Makefile2:104: recipe for target 'CMakeFiles/time_tool.dir/all' failed
make[1]: *** [CMakeFiles/time_tool.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

I have added in the CMakeLists.txt:

add_definitions(-D_GLIBCXX_USE_C99=1)

then it compiles ok, This could alternatively be defined in /cctz/src/time_tool.cc for GCC 5, as gcc 6 and 7 don't have this problem.

i am not sure this is the best way though, but i'd be happy to help fix it.

documentation suggestion for Windows data files

In this discussion of a Windows user trying to get cctz to work on Windows

https://groups.google.com/forum/#!topic/cctz/3tG-iyL3nf4

to get the binary zoneinfo files onto Windows she installs cygwin and runs zic.

It would be nice to put this information somewhere in the basic documentation, since Windows users need to bring in this zoneinfo data manually since Windows doesn't provide it in the needed format. (Some of the other steps from that thread would also be useful to include, such as #ifdef'ing out noexcept.)

However, the other important point to make about the zoneinfo files is that the incompatibility across platforms only seems to stem from big-endian/little-endian issues. So if you have a Mac (or other Linux) on an Intel machine (any modern Mac), I believe you can just .zip the zoneinfo directory and bring it over to your PC. I did this and everything seems to work fine. This was an easier process for me than having to install cygwin.

In fact it would be nice for you guys to include a .zip of the latest zoneinfo files right on this github site. Even for Mac/Linux people, packaged apps might want to include the data in app itself to have a backup plan it it's not available on the user's machine for some reason.

hello.cpp missing format parameter?

Is this a bug because it does not include the format string parameter? Crashes for me.

const std::string s = cctz::format("%F %T %z", tp1, syd);

Store a timezone

This may be a question about how to use the library rather than an issue. If so, many thanks for a pointer in the right direction.

I receive strings representing time and then store absolute time (in protobufs as int64):

// Time zone is required by cctz::Parse().  It is only used if the
// formatted time does not include offset info.
const auto utc = cctz::UTCTimeZone();
const char kFmt[] = "%Y-%m-%dT%H:%M:%E*S%Ez";
system_clock::time_point this_time_point;
if (!cctz::Parse(kFmt, date_str, utc, &this_time_point)) {
    cout << "Failed to parse time: " << date_str << endl;
    return 0;
}
return system_clock::to_time_t(this_time_point);

This works great. From time to time, I need to know local time for the original source. That is, I've received something like 2015-12-23 10:55:09+0100 and stored 1450864509. Now, in another process on another day, I see 1450864509 and want to recover 10:55 (i.e., for this absolute time, the corresponding local time was 10:55. For a concrete mental image, suppose I'm analysing when events correspond to lunchtime.

Of course, I can (outside of cctz) parse out the UTC offset and store that. I could also simply parse out the "HH:MM" string and store that. But those both seem quite wrong, and cctz seems well enough thought through that I'm guessing there's some way I haven't understood to persist an idea of a timezone.

And, if not, I suggest that this would be useful.

parse and ParseInt doesn't consider number length when parsing.

I have this string that was parsing correctly when using c date APIs.

Failed to parse '20180116 13:00' with format '%Y%m%d %H:%M'

Looking quickly at the code, the part of ParseInt is not bounded by the max length of a number (ie 4 for years).

However, I get why this is a complex question. How do you know if years is really in the 4 numbers? Can't parse years before 1000?

I'm thinking of doing a patch for this, but would like maybe some guidance as what you think is the best approach.

TimeZones.LoadZonesConcurrently test fails on mips platform

Dear all,

cctz was recently added to Debian archive [1] and was successfully built almost on all release relevant platforms [1].

There is only a problem with the TimeZones.LoadZonesConcurrently test, which is failing with " terminate called without an active exception" error:

`Start 2: time_zone_lookup_test [95/1830]

2: Environment variables:
2: TZDIR=/usr/share/zoneinfo
2: Test timeout computed to be: 1500
2: Running main() from gtest_main.cc
2: [==========] Running 31 tests from 7 test cases.
2: [----------] Global test environment set-up.
2: [----------] 1 test from TimeZones
2: [ RUN ] TimeZones.LoadZonesConcurrently
2: terminate called without an active exception
2/4 Test #2: time_zone_lookup_test ............***Exception: Other 0.04 sec
test 3
Start 3: time_zone_format_test`

For now we disable this test for mips, but it would be good to fix it properly.

[1] https://buildd.debian.org/status/package.php?p=cctz

Thanks you

Build with with MS Visual Studio

It would be interesting for cross-platform application.

Actually, I'm already work on it and will send pull-request for this issue.

New release for Abseil compatability?

I am trying to package Abseil, which depends on cctz. However, it seems that Abseil requires features of cctz that are not in the v2.0.0 release.

For example:

absl/time/time.h:1041:41: error: no member named 'name' in 'cctz::time_zone'
  std::string name() const { return cz_.name(); }

Are there plans to make another release that contains the features required by Abseil?

Recent commit 805a025 may break non-English mac users

Hello, while I'm debugging my strange segmentation fault, I reached to the patch 805a025.
805a025#diff-369c46982c3f44e7ed265e8576edfd4d

This patch introduced a call to CFStringGetSystemEncoding() mac api, but this api seems to be broken in our non-English mac machines (I confirmed in Japanese language). This function returns 0 (kCFStringEncodingMacRoman) for English users, but it returns 1 for Japanese users, which is an undefined value!
https://opensource.apple.com/source/CF/CF-299/String.subproj/CFString.h.auto.html

My mac version: 10.14.3
My xcode version: Version 10.0 (10A255)

Android compatibility

I'm looking into adding Android compatibility. Apart from a few build issues that can be fixed easily, it seems Android doesn't have the same timezone file layout as other systems.

Instead of subfolders in /system/usr/share/zoneinfo/, there's one big file that looks like it's the same format as other timezone files but I can't confirm that's the case.

Any idea how to work around or fix this problem? Thanks!

(BTW the library works great on iOS)

Timezone rules change over the time. Have you thought about that?

cctz::load_time_zone takes only the timezone name as a parameter, and returns the timezone rules that are in effect at the current moment in time. But the timezone rules themselves change over time.

Time zones often have a history of disparate rules that apply only for certain periods, because the rules may change at the whim of a region's local government.

What if the user needed a calendar representation of an absolute timestamp at the time of that timestamp, i.e. what was the civil time (the "wall time") at that time?

References:

Thank you.

Parse format "%Y%m%d" (no delimiter between fields)

Hi,

cctz::parse() seems to fail for format strings without delimiters: "%Y-%m-%d" works fine, however "%Y%m%d" fails (for input strings like "2014-03-04" and "20140304", the latter returns 1970-01-01).

Is this a known issue?

Kind regards,

Comparing two instances of cctz::time_zone

What is the right way to compare two instances of cctz::time_zone? Should there be some public implementation of operator == in class cctz::time_zone?

Rationale: At runtime time zones are loaded based on their name, often provided by user or external input. As multiple places and names can be located in/point to the same time zone (e.g. "America/Kentucky/Louisville", "America/New York" and "EST5EDT"), it is desirable to be able to check whether the two instances are referring to the same time zone without naively comparing the timezone name.

Get rid of default command line flags in Makefile

Having the default optimization level be hardcoded to -O is extremely inconvenient when trying to use CCTZ in automated builds. This should be -O2 or -O3 by default or simply not hardcoded so the environment variables take precedence. bazel is not present in the main repos for most major distributions.

Date-only & Time-only operations

This is more of a question than an issue.

This library feels to me like the C++ answer to Java 8's java.time package, or to Noda Time in .NET.

In those libraries (and many others), there are other APIs within the civil time domain that handle date-only or time-only operations. Are these things you're considering for cctz? Or is it just focused on the time-point to breakdown conversion problem?

For example, cctz:Breakdown is conceptually identical to LocalDateTime in the aforementioned libraries. However, those also have LocalDate and LocalTime structures, and cctz doesn't, as far as I can tell.

Use cases for these include:

  • Representing a whole civil day, rather than just a time within the day, such as birth dates.
  • Representing a time-of-day that isn't bound to a specific date, such as a repeating time.

cctz::parse error

i'm trying to use cctz::parse but it seems have a problem with some formats:

    std::cout << "scanTime : " << scanTime("1970 02 02","%Y %m %d") << std::endl;
    std::cout << "scanTime : " << scanTime("19700202","%Y%m%d") << std::endl;

first line produce 2764800.
second - error.

full code:

#include <iostream>
#include <cctz/civil_time.h>
#include <cctz/time_zone.h>
#include <chrono>
using SC = std::chrono::system_clock;
time_t scanTime(const char* str, const char* format)
{
    std::chrono::system_clock::time_point tp;
    if (!cctz::parse(format, str, cctz::utc_time_zone(), &tp))
        return 0;
    return SC::to_time_t(tp);
}
int main(void)
{
    std::cout << "scanTime : " << scanTime("1970 02 02","%Y %m %d") << std::endl;
    std::cout << "scanTime : " << scanTime("19700202","%Y%m%d") << std::endl;
    return 0;
}

Build on macOS broken since commit 805a025a896994ed507c9704cce15221bac6a632

Commit 805a025 is in Abseil as of a few days ago and it has broken macOS CircleCI builds.

The linker error:

Undefined symbols for architecture x86_64:
  "_CFRelease", referenced from:
      absl::time_internal::cctz::local_time_zone() in libabsl_time_zone.a(time_zone_lookup.cc.o)
  "_CFStringGetCStringPtr", referenced from:
      absl::time_internal::cctz::local_time_zone() in libabsl_time_zone.a(time_zone_lookup.cc.o)
  "_CFStringGetSystemEncoding", referenced from:
      absl::time_internal::cctz::local_time_zone() in libabsl_time_zone.a(time_zone_lookup.cc.o)
  "_CFTimeZoneCopySystem", referenced from:
      absl::time_internal::cctz::local_time_zone() in libabsl_time_zone.a(time_zone_lookup.cc.o)
  "_CFTimeZoneGetName", referenced from:
      absl::time_internal::cctz::local_time_zone() in libabsl_time_zone.a(time_zone_lookup.cc.o)
ld: symbol(s) not found for architecture x86_64

CircleCI run: https://circleci.com/gh/bstaletic/ycmd/241

undefined reference to 'clock_gettime'

nal/benchmark/src/timers.pic.o:timers.cc:function benchmark::ProcessCPUUsage(): error: undefined reference to 'clock_gettime'
bazel-out/local-fastbuild/bin/external/benchmark/_objs/benchmark/external/benchmark/src/timers.pic.o:timers.cc:function benchmark::ThreadCPUUsage(): error: undefined reference to 'clock_gettime'
collect2: error: ld returned 1 exit status

I'm building on Ubuntu/Linux 12.04.

Example DST dates incorrect

Haven't tried cctz yet, but just reading the docs and headers, found a mistake here

//   // A Spring DST transition, when there is a gap in civil time.
//   cctz::TimeInfo mar13 = cctz::MakeTimeInfo(2011, 3, 13, 2, 15, 0, lax);
//   // mar13.kind == TimeInfo::Kind::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

The spring forward transition in Pacific time moves from -0800 to -0700, so pre and post are swapped here.

Also, it seems strange to me to give the transition time like this. Though it reflects the same moment in time, usually we talk about the approaching time - that is, the time that never gets reached. In the US, people say DST occurs at 2:00 AM. Yes, that mean 03:00-0700 in the spring, and 01:00-0800 in the fall, but it would be odd to ever use them that way in describing the transition. Is there a reason for this part of the design?

Don't rely on *stream libray to polyfill strptime on Windows

std::get_time will pull in the bulk of *stream library and increase the binary size of the final executable a lot.

I know this is a big ask for cctz team because strptime is very complicated to implement, but we have a requirement to not rely on *stream library for binary size concern.

Conan Package Support

Hello,

Do you know about Conan?

Conan is modern dependency and package manager for C/C++. And will be great if your library will be available via package manager for other developers.

Now we have famous C++ projects, including Google Flatbuffers. We could support you writing a recipe and publishing your packages on Bintray.

If you have any questions, just ask :-)

MinGW compiler errors on Windows

_dupenv_s()
_get_timezone()
_get_tzname()

are Microsoft Visual Studio compiler functions only (as far as I know). The MinGW compiler (and probably any other compiler) doesn't know these funtions.

So for the obove mentioned functions the macros

if defined(_WIN32) || defined(_WIN64)

should be changed to

if defined (_MSC_VER) // Microsoft Compiler only

in the files time_zone_info.cc, time_zone_libc.cc and time_zone_lookup.cc.

sys_seconds is a duration in cctz, but a time_point in C++20

https://en.cppreference.com/w/cpp/chrono/system_clock shows that C++20 has adopted sys_seconds as:

template<class Duration>
using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>; 
using sys_seconds = sys_time<std::chrono::seconds>;

whereas cctz defines it as

using sys_seconds = std::chrono::duration<std::int_fast64_t>;

Yes, they are in different namespaces, but it would be great if the two were unified, especially if you aim to have cctz adopted as part of the C++ standard.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.