mirror of
https://github.com/HowardHinnant/date.git
synced 2025-08-04 21:24:26 +02:00
Updated FAQ (markdown)
82
FAQ.md
82
FAQ.md
@@ -3,6 +3,7 @@
|
|||||||
- [Why is `%A` failing?](#week_day_parse_bug)
|
- [Why is `%A` failing?](#week_day_parse_bug)
|
||||||
- [Why is `local_t` not a proper clock?](#local_t)
|
- [Why is `local_t` not a proper clock?](#local_t)
|
||||||
- [Why can't I compare instances of `zoned_time`?](#zoned_time_comparison)
|
- [Why can't I compare instances of `zoned_time`?](#zoned_time_comparison)
|
||||||
|
- [Why is `weekday` encoded with [0, 6] as [Sun, Sat] instead of the ISO [1, 7] as [Mon, Sun]?](#weekday_encoding)
|
||||||
***
|
***
|
||||||
|
|
||||||
<a name="day_arithmetic"></a>
|
<a name="day_arithmetic"></a>
|
||||||
@@ -128,3 +129,84 @@ This compiles and will do exactly what it looks like it does: Sleeps until Nov.
|
|||||||
When working with `zoned_time` objects, it seems natural that one should be able to make comparisons between two instances in relation to the instant in time each represents. Though each `zoned_time` references a `sys_time`, it also has an associated local timezone complicates the consideration of how operators like `<` should be defined. Such operations could be defined relative to `sys_time` or to `sys_time` and `time_zone*`, though there are issues with each. For two instances of `zoned_time` `x` and `y`, `operator<` could be defined as `x.get_sys_time() < y.get_sys_time()`; however, there would then be cases where `!(x < y) && !(y < x) && x != y`, which breaks not only with tradition but probably several algorithms as well. I.e. if `x` and `y` have the same `sys_time`, but different `time_zone*`.
|
When working with `zoned_time` objects, it seems natural that one should be able to make comparisons between two instances in relation to the instant in time each represents. Though each `zoned_time` references a `sys_time`, it also has an associated local timezone complicates the consideration of how operators like `<` should be defined. Such operations could be defined relative to `sys_time` or to `sys_time` and `time_zone*`, though there are issues with each. For two instances of `zoned_time` `x` and `y`, `operator<` could be defined as `x.get_sys_time() < y.get_sys_time()`; however, there would then be cases where `!(x < y) && !(y < x) && x != y`, which breaks not only with tradition but probably several algorithms as well. I.e. if `x` and `y` have the same `sys_time`, but different `time_zone*`.
|
||||||
|
|
||||||
In the case that comparison is required by an application, named functors or lambdas defining the comparison operations should be used.
|
In the case that comparison is required by an application, named functors or lambdas defining the comparison operations should be used.
|
||||||
|
|
||||||
|
<a name="weekday_encoding"></a>
|
||||||
|
### Why is `weekday` encoded with [0, 6] as [Sun, Sat] instead of the ISO [1, 7] as [Mon, Sun]?
|
||||||
|
|
||||||
|
As this library developed, a decision about `weekday` encoding had to be made. There were two existing competing standards:
|
||||||
|
|
||||||
|
1. C and C++ in the encoding of `tm.tm_weekday` which maps `[0, 6]` to `[Sun, Sat]`.
|
||||||
|
|
||||||
|
2. ISO which maps `[1, 7]` to `[Mon, Sun]`.
|
||||||
|
|
||||||
|
Implicit in each of these encodings is the answer to the question: What is the first day of the week? And the answer depends upon your locality or culture. Monday is the first day of the week according to the international standard ISO 8601, but in the US, Canada, and Japan it's counted as the second day of the week.
|
||||||
|
|
||||||
|
This library seeks to not answer this question, and thus leave the answer up to the client. Indeed this library doesn't even force a decision to Sunday or Monday. It could be Thursday for all this library cares. How does it do this?
|
||||||
|
|
||||||
|
First, `weekday` has no `operator<()`. Sunday is neither less than or greater than Monday. Sunday is simply not equal to Monday. If you have to store `weekday` in an associative container you will have to come up with your own ordering function.
|
||||||
|
|
||||||
|
Second, subtraction of one `weekday` from another is unsigned modulo 7 arithmetic. That is, no matter what weekday you subtract from another, you will always get an answer with the type `days` with a value in the range `[days{0}, days{6}]`. This definition of subtraction for `weekday` has a profound impact on calendrical algorithms that compute with `weekday`s. It makes every algorithm _encoding independent_.
|
||||||
|
|
||||||
|
For example, let's say you want to write an algorithm that takes a `sys_days`, and computes the next Tuesday, with the proviso that if the current day is a Tuesday, then the result is the same day (not important to the point, just to nail down a specific algorithm). That might look like:
|
||||||
|
```c++
|
||||||
|
date::sys_days
|
||||||
|
next_Tue(date::sys_days x)
|
||||||
|
{
|
||||||
|
using namespace date;
|
||||||
|
return x + (Tuesday - weekday{x});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This computes the current `weekday`, and then subtracts it from `Tuesday` and adds that many `days` to the current date. The important thing to notice about this algorithm is that it is _independent_ of the underlying encoding of `weekday` as long as `weekday` subtraction is unsigned modulo 7. `Tuesday` is _always_ ahead of `weekday{x}` by some number of days in the range of [0, 6].
|
||||||
|
|
||||||
|
These two characteristics make the encoding of `weekday` much less important, except perhaps for those wishing to format or parse `weekday` as an integer. C and POSIX provide two ways to format a weekday as an integer: `"%w"` and `"%u"`, using `strftime` will deal with both the [0, 6] and [1, 7] mappings. This library supports these same mappings with `format`. Additionally POSIX supports `"%w"` (but not `"%u"`) for parsing (with `strptime`). This library support _both_ `"%w"` and `"%u"`, using `parse`. So this library provides the same support for the [0, 6] mapping as POSIX (and better than C), and _better_ support for the [1, 7] mapping than both C and POSIX.
|
||||||
|
|
||||||
|
This better support takes two forms: Reducing the importance of the encoding on calendrical algorithms, and better parsing support for the ISO [1, 7] encoding.
|
||||||
|
|
||||||
|
But ultimately this library chose the [0, 6] encoding. Why?
|
||||||
|
|
||||||
|
This library was written to enable clients to abandon the ancient C/POSIX `<time.h>` API. However the reality is that clients still often have to interoperate with legacy code that uses the old `<time.h>` API. This old API using the [0, 6] encoding for the `tm_wday` member of the `struct tm`. It is easier on the client to maintain encoding compatibility with `struct tm` than it is if this library rigidly stuck to the ISO encoding. With this compatibility, filling out the `tm_wday` member of `struct tm` is as easy as:
|
||||||
|
```c++
|
||||||
|
tm.tm_wday = unsigned{wd};
|
||||||
|
```
|
||||||
|
And ease translates to less error-prone code.
|
||||||
|
|
||||||
|
As a demonstration of the lowered importance of weekday encoding in calendrical algorithms, see [how to print a calendar](https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes#calendar) which is configurable on the first day of the week. For example here is how to use this code to make Thursday the first day of the week:
|
||||||
|
```c++
|
||||||
|
print_calendar_year(std::cout, 3, 2018_y, Thursday);
|
||||||
|
```
|
||||||
|
which outputs:
|
||||||
|
```
|
||||||
|
January 2018 February 2018 March 2018
|
||||||
|
Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We
|
||||||
|
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7
|
||||||
|
4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14
|
||||||
|
11 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21
|
||||||
|
18 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28
|
||||||
|
25 26 27 28 29 30 31 29 30 31
|
||||||
|
|
||||||
|
April 2018 May 2018 June 2018
|
||||||
|
Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We
|
||||||
|
1 2 3 4 1 2 1 2 3 4 5 6
|
||||||
|
5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
|
||||||
|
12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
|
||||||
|
19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
|
||||||
|
26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
|
||||||
|
31
|
||||||
|
|
||||||
|
July 2018 August 2018 September 2018
|
||||||
|
Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We
|
||||||
|
1 2 3 4 1 1 2 3 4 5
|
||||||
|
5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12
|
||||||
|
12 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19
|
||||||
|
19 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26
|
||||||
|
26 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30
|
||||||
|
30 31
|
||||||
|
|
||||||
|
October 2018 November 2018 December 2018
|
||||||
|
Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We
|
||||||
|
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5
|
||||||
|
4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12
|
||||||
|
11 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19
|
||||||
|
18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26
|
||||||
|
25 26 27 28 29 30 31 29 30 27 28 29 30 31
|
||||||
|
```
|
Reference in New Issue
Block a user