mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-29 19:12:03 +00:00
193 lines
8.4 KiB
Markdown
193 lines
8.4 KiB
Markdown
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/civil_time.h`]
|
||
(https://github.com/google/cctz/blob/master/include/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/time_zone.h`](https://github.com/google/cctz/blob/master/include/time_zone.h).
|
||
|
||
These libraries are currently known to work on **Linux** and **Mac OS X**. We
|
||
are actively interested in help getting them working on Windows. Please contact
|
||
us if you're interested in contributing.
|
||
|
||
# Getting Started
|
||
|
||
CCTZ is best built and tested using the [Bazel](http://bazel.io) build system
|
||
and the [Google Test](https://github.com/google/googletest) framework. (There
|
||
is also a simple [`Makefile`](https://github.com/google/cctz/blob/master/Makefile)
|
||
that should work if you're unable to use Bazel.)
|
||
|
||
1. Download/install Bazel http://bazel.io/docs/install.html
|
||
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`
|
||
|
||
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:
|
||
* Civil Time: [`include/civil_time.h`](https://github.com/google/cctz/blob/master/include/civil_time.h)
|
||
* Time Zone: [`include/time_zone.h`](https://github.com/google/cctz/blob/master/include/time_zone.h)
|
||
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:
|
||
* https://groups.google.com/forum/#!forum/cctz
|
||
|
||
# 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. http://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>`](http://en.cppreference.com/w/cpp/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/civil_time.h`](https://github.com/google/cctz/blob/master/include/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/time_zone.h`](https://github.com/google/cctz/blob/master/include/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 "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 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 "civil_time.h"
|
||
#include "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 [FAQ](https://github.com/google/cctz/wiki/FAQ)
|
||
* See also the [Time Programming Fundamentals](https://youtu.be/2rnIHsqABfM)
|
||
talk from CppCon 2015 ([slides available here](http://goo.gl/ofof4N)). This
|
||
talk mostly describes the older CCTZ v1 API, but the *concepts* are the same.
|
||
* ISO C++ proposal to standardize the Civil-Time Library:
|
||
https://github.com/devjgm/papers/blob/master/d0215r1.md
|
||
* ISO C++ proposal to standardize the Time-Zone Library:
|
||
https://github.com/devjgm/papers/blob/master/d0216r1.md
|