Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

number series (continued)

Status
Not open for further replies.

Chris Miller

Programmer
Oct 28, 2020
4,897
DE
As contiuation of thread1551-1811866

Let me spoil as far as the series has to do with the calendar. I think it's still appropriate to wish you a Happy New Year and I thought I'd continue with the puzzle a bit.

Further spoilers and explanations in spoiler tags...

First a summary of the questions asked:

31,61,92,122,153,184,214,245,275,306,337

1. How is this number series helpful.
It's created by rounding n*30.6 to the nearest whole number.

2a) How to determine the days passed in the current month? See spoiler in the linked thread, in short:
Well, that's simply the days of a date, or off by one, if you want to be strict.

2b) when you don't want to rely on the date having a correct day part, what can you do, besides knowing how long months are?
2c) what about days in February in leap years?
The previous spoiler suggests computing the difference of an entered date (assumed to be correct) to the first of next month (which is easy to construct without knowing month length, of course), and then compute the difference. The difference of 29th February to 1st March in leap years will be 1, indicating that there is the leap day, or 0 in non-leap years. That implies having such a formula, the number series points in that direction, while it starts counting on March 1st and is not yet clear on how to deal with January and February dates, but we'll get there.

The goal now has shifted to computing a day number, yet another spoiler: The goal is a Julian day number, that's the number of days past a specific ultimo date. It doesn't have to be that specific, any ultimo date is okay to be able to use such a day number for further usual date computation problems like date differences (they simply become differences of day numbers) or determining the weekday (make any Monday or Sunday the ultimo date and weekdays become the day number mod 7). It's also the base idea of UNIX timestamps in seconds or nanoseconds, but one step after the other...

3) What about this "magic number" 30.6? is it really that magic?

30.6 is just the shortest in decimal representation. There is a small window from about 3.591 to 3.681 where this works. Which is not to be expected from computing 365/12. For a whole year the short February skews it too much, but when starting to count in March it evens out better, the average month length of March to next years January is 337/11, approximately 30.64 days.

Correction of my previous spoiler: In binary with bits of value 1/2, 1/4, 1/8, 1/16, etc. , I haven't checked what's the shortest. I later came up with 979, binary 1111010011. If you divide that by 32 you get exactly 30.59375, which is near 3.6 and, more important, within the valid interval. Karluk computed the interval more precise in the form of quotients, by the way. The main advantage is now you can do integer operations, which run much faster than floating point.

4) Final question: How about computing the (a) Julian day number of a date knowing all that?

I'll get back to this in a few days. Greetings, especially to karluk.

Chriss
 
Chriss, I think you're absolutely right that 979/32 is the fraction with the smallest denominator which is both in the right range to replace 30.6 in your calendar calculations and can also be expressed as a terminating fraction in binary. The options with smaller denominators are 245/8 = 30.625 and 489/16 = 30.5625, both of which are out of range.

Thank you very much for following up on the earlier thread. I will be very interested to see where your calculations take you.
 
To be honest, I had a bit of issue in migration to new hardware.

And after I reimplemented my idea I found the JS code I wrote earlier in my browsers devtools.

Now I have two implementations that are not fully congruent in their results and I have to find out whather the old or the new me is right, so to say.

In short the idea is:
Take a normal date in d,m,y subtract three months (or add 9, doesn't really matter) so the month numbers relate from 0 for March to 11 for February. This way you can compute the contribution to an overall day number of the month by the number series we talk about all the time. ears contribute 365.25*y and days, are, well, days. There must be a correction for ever 100 years but not every 400 years.

Once you have such a number you have a general measure of past days since some ultimo date and can transpose between different calendars. And the fun is it all is just some simple integer maths.

Chriss
 
Okay, here's a alpha version of a date class that computes the Julian day number With the help of the number series, instead of relying on unixdate. The computation of JDN is much simpler with unix timestamp, by the way, as it just has some offset to seconds since (1970/1/1/0:00:00 am)/86400.

Still, I think it's nice to see a way of calculating this from scratch with simple math.

Code:
class anyDate {
  anyYear = 0;
  anyMonth = 0;
  anyDay = 0;
  anyDays = 0;

  // y,m,d (or partial dates)
  // For example, new cmDate(y) is todays date in year y.
  // If today is 29th February and y isn't a leap year,
  // the date shifts to March 1st in year y.

  // note: Internall anyYear works with a calendar starting on March 1st Year 0.
  //       Therefore the gregorian date is shifted by 3 months.
  //       Still usage is with Month in 1..12.
  constructor(...dateparts) {

    var jsDate;

    switch(dateparts.length) {
        case 0: 
          jsDate = new Date();
           break;
        case 3:
        case 2:
           // when month is given (2 or 3 parameters)
           // reduce it by 1 for JS Date(y,monthindex,d) with monthindex 0..11
           dateparts[1]--;
           // no break here, default has to be executed in any case but 0 parameters.
           // In the special case of 1 parameter, only dateparts[0] is defined
           // so only cases 2 and 3 have to decrement the month to a monthindex. 
        default:
           // with any number of passed in parameters they can be passed on now,
           // with usually rectified month.
           jsDate = new Date().setFullYear(...dateparts);
           // new Date().setFullYear(y[,monthindex[,d]]) is used, 
           // because new Date(x) is Unix epoch time + x milliseconds,
           // not todays date in year y.
           //in contrast setFullYear() allows 1 to 3 parameters, including any year.
    }
  
    this.anyYear = jsDate.getFullYear();
    this.anyMonth = jsDate.getMonth()-2; // only -2, since month is 0 based.
    // note: anyMonth like js Date class is 1 based, but still uses month mod 12 
    ///      numbers for calculations with 0 meaning March.
    this.anyDay = jsDate.getDate();

    // adjust year, if necessary
    if (this.anyMonth<0) {
       this.anyMonth+=12;
       this.anyYear-=1;
    }
   
    var yeardays = ((this.anyYear*11688)>>5)|0;
    
    //var templeap = (this.anyYear/400|0) - (this.anyYear/100|0);
    var leapdays = (this.anyYear/100)|0;
    leapdays = ((leapdays>>2)|0)-leapdays;

    var monthdays = (this.anyMonth*979+0x10)>>5|0;

    this.anyDays = 1721119+yeardays+leapdays+monthdays+this.anyDay;
  }
}

<!-- Note: The offset 1721119 is unimportant, it's just shifting the daynumber to be the julian day number (JDN) and is used to compare the result with other JDN calculations. 

JDN mod 7 is 0 for Mondays, not sure if it's by choice of the ultimo date, since there is a gap of 10 days in October 1582. Besides for astronomical use JDN typically is shifted half a day to local time to have the same JDN for astronomical observations during nights. -->

My next steps will be enriching this with date transposing to other calendars including historic calendars, taking into account where which calendar was introduced. But this will just be tedious.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top