GithubHelp home page GithubHelp logo

Year greater than 2^16 about date HOT 8 CLOSED

romikforest avatar romikforest commented on May 12, 2024
Year greater than 2^16

from date.

Comments (8)

HowardHinnant avatar HowardHinnant commented on May 12, 2024

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.

romikforest avatar romikforest commented on May 12, 2024

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.

HowardHinnant avatar HowardHinnant commented on May 12, 2024

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.

romikforest avatar romikforest commented on May 12, 2024

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.

HowardHinnant avatar HowardHinnant commented on May 12, 2024

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.

HowardHinnant avatar HowardHinnant commented on May 12, 2024

Closing as not-to-be-fixed.

from date.

nabijaczleweli avatar nabijaczleweli commented on May 12, 2024

You should mark it with the wontfix tag, then, @HowardHinnant

from date.

HowardHinnant avatar HowardHinnant commented on May 12, 2024

Thanks!

from date.

Related Issues (20)

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.