[/
    Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
   
    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]

[section:time_types Time types: date, datetime and time]
[nochunk]

The [reflink date], [reflink datetime] and [reflink time] provide
support for MySQL's native date and time types. This section expands
on how to use them.

[heading The date type]

[reflink date] represents MySQL __DATE__ in C++. `date` holds the year, month and day components of a date.
It is a type close to the protocol, rather than a vocabulary type. The main reason for using `date` instead
of a `std::chrono::time_point` type is that, under certain configurations, MySQL allows storing invalid
dates, such as `2020-00-01`. These are not representable as a `std::chrono::time_point`.

Unless dealing with these special values, we recommend converting `date`s to a `time_point` before using them.
The member type [refmem date time_point] is a system-clock `time_point` that can represent the entire
MySQL `DATE` range without problems. You can use [refmem date as_time_point] to perform the cast:

[time_types_date_as_time_point]

If the date is not valid, `as_time_point` will throw an exception.

You can query whether a `date` contains a valid date or not using [refmem date valid]:

[time_types_date_valid]

You can combine it with [refmem date get_time_point], which performs an unchecked
conversion:

[time_types_date_get_time_point]

You can also construct a `date` from a `time_point`. If the `time_point` is
out of range, an exception is thrown.



[heading The datetime type]

[reflink datetime] represents MySQL __DATETIME__ and __TIMESTAMP__ in C++. `datetime` represents a broken time point,
having year, month, day, hour, minute, second and microseconds.

MySQL also accepts invalid datetimes (like `2020-00-10 10:20:59.000000`). The same considerations for
`date` apply:

[time_types_datetime]

The `datetime` object doesn't carry any time zone information with it. The time zone semantics
depend on the actual MySQL type:

* __DATETIME__ is a "naive" time point object. It represents a time point without any time zone
  information at all. It is up to the user to interpret which time zone the object is in.
* When a __TIMESTAMP__ object is inserted, it is interpreted  to be in the connection's local time zone,
  as given by the __time_zone__ variable, and converted to UTC for storage. When retrieved, it is converted back
  to the time zone indicated by __time_zone__. The retrieved value of a `TIMESTAMP`
  field is thus a time point in some local time zone, dictated by the current
  __time_zone__ variable. As this variable can be changed programmatically from SQL, without
  the library knowing it, we represent `TIMESTAMP`'s using the `datetime` object, which doesn't include time zone information.

When using `TIMESTAMP`, we recommend setting the __time_zone__ to a known value. To illustrate this,
consider an event-logging system with the following table definition:

[time_types_timestamp_setup]

We will be inserting events with an explicit timestamp. We may also want to retrieve events with
a timestamp filter. This is what our prepared statements would look like:

[time_types_timestamp_stmts]

These statements may be run from different parts of our code, or even from different applications.
To get consistent results, we must make sure that the time zones used during insertion and retrieval are the same.
By default, __time_zone__ gets set to `SYSTEM`, which will use the server's time zone settings.
This is not what we want here, so let's change it:

[time_types_timestamp_set_time_zone]

With this, the insertion code can look like:

[time_types_timestamp_insert]

The querying code would be:

[time_types_timestamp_select]
    
If you don't set __time_zone__, you may apparently get the right results if you run
both insertions and queries from clients that don't set `time_zone` and the server doesn't
change its configuration. However, relying on this will make your applications brittle, so we
don't recommend it.


[heading The TIME type]

The __TIME__ type is a signed duration with a resolution of one microsecond.
It is represented using the [reflink time] type, an alias for a
`std::chrono::duration` specialization with microseconds as period.


[endsect]
