Comments (8)
The year
type is stored in a signed 16 bit integer, and this is done because many clients will want sizeof(year_month_day) == 4
, and very few care about calendrical computations more than +/- several thousand years.
However here: http://howardhinnant.github.io/date_v2.html search for the section titled "Extensibility". I think this could be a good direction for you: Create a custom field type (with the year storage as big as you want), and create implicit conversions between this type and day_point
(as demonstrated for iso_week
in the paper). Once you have this, you have complete interoperability with the entire date.h library.
You will probably want to use the algorithms documented here: http://howardhinnant.github.io/date_algorithms.html to perform those conversions. The algorithms are good for +/- 5.8 million years using a 4 byte signed year, and with an 8 byte signed year the range is far greater than +/- the age of the universe.
from date.
I think it would be a good idea to define some typedefs at the top of the data.h or in external configuration file and to use them in other code for types to do the library easily adaptable.
from date.
I've given this a lot of thought. And date.h is the wrong tool for what you're doing. Though I think <chrono>
is a very good tool.
Rationale: date.h models the Gregorian year, and does it very well. The Gregorian year models the tropical year, and is accurate to about 1 day in 3200 years. date.h has a range somewhat greater than that purely for overflow protection purposes. And by storing the year in a signed 16-bit integer, we keep a small size and cover more than enough range for the Gregorian calendar (society will likely abandon or adjust the Gregorian calendar in several thousand years). Computing the day of the month, or day of the week hundreds of thousands of years in the past or future (using the current Gregorian calendar) is of dubious value.
That's not to say that computing time this far in the past or future is not valuable: it is! But you should use units more suited for your task, and those units are almost certainly not Gregorian years. And the <chrono>
library can help you do this.
For example if you need to measure seasons, using a better approximation to the tropical year would be a good choice (even though the tropical year is not a constant). It is currently about 31,556,925 seconds (compared to the Gregorian year of 31,556,952 seconds). If you are investigating astronomy, it could be that the sidereal year is a more appropriate measure: 31,558,149.5 seconds. <chrono>
will allow you to easily set up all of these units.
These may seem like small differences. But when multiplied over the time scales you are talking about, they make a difference, and will almost certainly obsolete the Gregorian calendar.
Still, if you are dead-set on using the Gregorian calendar this far into the past or future, please feel free to use the algorithms at http://howardhinnant.github.io/date_algorithms.html. They will do the job.
from date.
I see, and you are right. I very liked your library and have adapted it for my code (I haven't seen all code, but what I had tested works correct). Really, my purpose is not to do calculations for 10^22 Gregorian years or 5*10^11 ages of the University with precision 1 nanosecond. And it is not my purpose to use only Gregorian calendar. I'm just writing one library and have external time data in three formats, each uses 64 bit integer and saves period from unix epoch but in different units: seconds (standard unix timestamp), microsecond (python timedate) and nanoseconds (std::chrono::system_clock). As std::chrono 64 bit representation can save only about +- 200 or 300 years and as I'm writing in c++ I had used std::chrono templates but with 128 bit integer for underlying type and was searching for a library, that can correct represent time as calendar data in some more big diapason without that troubles with ctime.h in multi-threaded applications. 128 bit integer has a very big range, may be slowly and so on, but it logically goes after 64 bit, it includes range of external incoming data and at the moment don't seems to slow much my project. I just have done some general interface, and it is not my business for what very theoretical or annoying purposes it can be used. My representation includes all incoming ranges and has no overflow with dates showing something like 1960 for 3000, if somebody will use such time intervals. And I have declared some using definitions, that can be always adjusted to use other types, even have macro guards to be possible adjust them from one configuration header file for all project, included before my modification of date.h. I'm very glad to use date.h and thank you very much for it. I just note, what as you have done this work and have that templated algorithms and so on, you can easily done more general library, include more calendars, at least from used now in different countries and do it in some more general way, and I more trust you than my hack I have done. But any way, date.h is a very good thing even without that.
from date.
Thanks for your kind words. I think the use of __int128_t
to store nanoseconds is interesting. And I applaud your efforts to reduce the chances of overflow.
While developing tz.h I did experience one case of overflow that surprised me (and it is my own stupid fault). I'm telling you this story in the hopes that you will avoid the same trap. std::chrono::minutes
is only required to be 29 bits, and in practice sometimes is 32 bits. That's about +/- 4083 years worth of range (which you think would be enough). However I found that day_point{year::max()/jan/1} + 0min
was overflowing (with year::max() == 32767
) and that this was an easy situation to run in to within the timezone library implementation. The overflow doesn't happen if minutes is stored in 8 bytes instead of 4, because the day_point{year::max()/jan/1} + 0min
computation gets "promoted" to 8 bytes.
In hindsight I wish I had specified that hours, minutes, seconds, milliseconds and microseconds have a range to at least +/- 32768 years (can't do much about nanoseconds). Because of this problem, if you are on a platform with a 4 byte minute, year::min() and year::max() are reduced enough so as to not cause overflow in computations such as this. With an 8 byte minute, year::min() and year::max() are constrained by the range of int16_t.
If I had a time machine, I would add several bits to the minimum size of 5 of the chrono durations:
nanoseconds at least 64 bits
microseconds at least 61 bits
milliseconds at least 51 bits
seconds at least 41 bits
minutes at least 36 bits
hours at least 30 bits
from date.
Closing as not-to-be-fixed.
from date.
You should mark it with the wontfix
tag, then, @HowardHinnant
from date.
Thanks!
from date.
Related Issues (20)
- How to use date/tz.h properly HOT 4
- When I compile on x64 uwp I get the error HOT 1
- Waybar fails to compile with clang/libcxx because of date/tz.h HOT 8
- Change the type of the data member of class year to int from short HOT 3
- Undefined symbol HOT 1
- date_test_pass_parse_test fails with gcc (Debian 10.2.1-6) 10.2.1 20210110 HOT 1
- Date Parse: one pattern for ISO8601 DATE or DATE TIME HOT 6
- How can I convert between std::chrono::time_point and string (2023-12-06 00:46:45.801479+08)? HOT 4
- OSSFuzz Integration HOT 9
- Incorrect value of date::sys_info::save HOT 1
- Cannot override CMake options when fetching the library via FetchContent_Declare()
- .zip files have "text" git attribute HOT 1
- Possibly big performance improvement for `time_zone::to_sys()` HOT 10
- Failed to install tzdb HOT 2
- Transform date::local_seconds and timezone offset to struct tm HOT 1
- Missing tz.h header file when selecting compiler for ARM architecture HOT 1
- Opposite inner 'if' condition leads to a dead code block HOT 1
- Use timezone name like "-08:00" for `locate_zone()` HOT 2
- date::parse() doesn't have a formatting character for ISO 8601 strings without 'T' separator HOT 2
- How to parse datetime with milliseconds and timezone? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from date.