© J R Stockton, ≥ 2009-09-16

Date and Day Count.

Links within this site :-
This page is about converting Daycount to/from Y M D by plain arithmetic; JavaScript is used merely because it is commonly executable in Web browsers. In languages in which date handling is provided, it may, or may not, be better to use the built-in provisions.

Introduction

Astronomers and others need calendar conventions in which the date and the day number are independent of location; for this, GMT/UTC and Julian Day Number & Modified Julian Date are appropriate.

GMT here refers to British legal GMT, in which the pre-1925 Astronomical 12-h shift is disregarded. The GMT date changes at London mean solar midnight.

More often, though, one needs a convention in which the local civil date and the day number change simultaneously; for this, Chronological Julian Date & Chronological Modified Julian Date are appropriate. Chronological Julian Day Number & Chronological Modified Julian Day Number are alternative terms.

In computing, other origins are often somewhat arbitrarily chosen - see Date and Time Scales.

It is often easier, or more efficient, to work in terms of day numbers, converting to/from calendar dates for output/input, than to work with year, month, and day.

"Mapping Time" (OUP), by E.G.Richards (EGR), contains much related information.

References to Julian day number in code and links are quoted, and actually refer to Chronological Julian Date.

For financial work, consider Wikipedia Day count convention but be aware of varying local convention.

Addendum for converting from Y M D

To allow for dates before 0000-03-01, add a multiple of 400 (Gregorian), 28 (Julian), or 2800 (both) years to y and, unless wanting only Day-of-Week, adjust the constant term correspondingly.

The method may not be optimum; starting with Year = (Year + Bias) mod 400 (Bias not needed for A.D. years) might reduce subsequent arithmetic.

Or use Math.floor(X) instead of X|0 which should automatically widen the range.

Conversions between Calendars

Conversion between closely-related Calendars can be done with simple difference rules such as that in Date and Time Scales. Otherwise, the best policy is to implement, for each Calendar, conversions in each direction between Date and Day-Count.

The Day-Count should be a well-defined one with a standard origin, and should change at the same time as the Date. It should be explicitly based, either on legal GMT or on local time.

Julian Date (JD) changes at noon GMT, Modified Julian Date (MJD) at midnight GMT; so those are not suitable. Generally one should use their "Chronological" versions (CJD, CMJD), which refer to the local civil day.

For some non-Christian Calendars, see via other pages :-

For Calendars in which the Date changes other than at midnight, be very careful about the matching of Dates to Days. For example, it is not usually made clear, when the origin of the Islamic Calendar is given in Christian terms, whether MuHarram 1, 1 A.H. maps to the Julian Calendar Date on which it started or to the following Date with which it had a larger overlap.

Date to/from Numeric String

To represent a date Y M D as an eight digit string, it may be convenient to use a pseudo-date number such as PD = (Y×100+M)×100+D first; that transformation is readily reversible either with div and mod or with string operations. That format is also convenient for sorting, as number or string.

Conversions between Day-Count and Common Date

Zeller's Congruence (or Algorithm) gives Day-of-Week from Calendar Date. Methods, often attributed to Zeller, which use the same principles help to convert Calendar Date to Day-Count.

Computer languages often have primitives or library routines which implement, or can be used in, conversions. Such may be employed in test routines here, but the conversion routines shown do not use them. Code tested here is JavaScript.

Various arithmetical methods exist for dealing with the Leap Year rules in converting between day number and year number; either manifestly embodying the rules, or condensed either for numerical efficiency or for simplicity. Some are included in my dateprox.pas. Many are given in books such as "Mapping Time".

For JavaScript, see also in my JavaScript Date and Time 1 : Date Arithmetic, which was mostly not directly developed from Zeller's papers.

Year Range

Various methods are valid over various year-ranges. Before using any over a wide range, test carefully against a method which will have a wide range, such as one using a Date Object.

Notation

Here the conversions are illustrated and tested in JavaScript.

The expression a % b is the remainder operation, equivalent to a mod b in Pascal; the integer part from the implied division is disregarded.

The expression (a/b)|0 using the bitwise OR operator is integer division, equivalent to a div b in Pascal; the remainder is disregarded. And Math.floor(a/b) is a wider-range but slower version.

The expression (a>>2) is integer shift right 2, equivalent to integer division by 4.

And M += 12 is increment by 12, and y-- is decrement by 1, and // starts comment to end-of-line, and /* ... */ is comment. The rest should now be obvious enough.

Some Constants

The origin of JavaScript dating, 1970-01-01 GMT, is MJD 40587.

CMJD -678973 is the day before the month before A.D. 0, Gregorian; that is date 0000-00-00.

Ordinarily, in Gregorian, a year has 365 days, a span of 4 years has 1461 days, and 100 years have 36524 days; but 400 years always have 146097 days.

Initialise EGR Constants

Some of what follows is derived from the algorithms Web page for "Mapping Time" (a), in which the following constants are used.

For the Julian Calendar

For the Julian Calendar, omit the lines which assign to g in EGR-derived functions; and omit the obviously inapplicable Leap Year terms or lines and adjust the zero (probably by 2) in others.

Gregorian Date to Day-Count

Tester

The following tester harmlessly includes out-of-month dates.
2007-04-03: Loop start d=0 changed to d=1 as Firefox 2.0.0.3 Date.UTC takes d<1 as d=1 (2.0.0.14 - unchanged; 3.0 - fixed).

N.B. window.status shows progress, if enabled.

Zellerish

Two versions, essentially the same :

1

This, for CMJD, was developed in The Calendrical Works of Rektor Chr. Zeller : The Day-of-Week and Easter Formulae, section moved to Material Related to Zeller's Congruence., q.v.; the fastest method that I know of, and I doubt whether it can be much improved upon. This is the clearest version of the code.

2

This, for CMJD, was developed from the Day-of-Week code in Wikipedia Zeller's congruence.

Optimising

This version of the code is in inc-date.js.

Recursive Form

After Mike Keith

Modified by me from Mike Keith's day-of-week algorithm F1 in my subsidiary Zeller page.

EGR, Algorithm E

Unoptimised
Optimising

F & F

The Fortran algorithm is cited in Julian Day Numbers by Peter Meyer, Sec 9 :-

Using a Date Method

The latter illustrates the folly of using local dates where UTC can be used instead.

Day-Count to Gregorian Date

The reverse calculation can be done in various ways; I have sought a style-matching and efficient version.

Testers

These two functions each test a function below.

N.B. window.status shows progress, if enabled.

Individual Rules

This has a straightforward way of determining the year :-

Paired Rules

It is somewhat faster with the Julian and Gregorian Rules done by congruences, and Math.round replaced; this version of the code is in inc-date.js :-

EGR, Algorithm F

Unoptimised
Optimising

F & F

Adapted from Henry Fliegel and Thomas van Flandern, ACM Vol 11, 1968 (by mail from HJW 20051228); also see Julian Day Numbers by Peter Meyer, Sec 9.

Using a Date Object

N.B. Much of the work will be repeated three times, once for each getUTC... function call.

VBScript

See in my VBScript Date and Time 1.

Conversions between Day-Of-Year and Common Date

These do not use an absolute Day-Count.

Where, as in JavaScript, Delphi, etc., the language provides relevant pre-coded Date methods, it is likely that those will perform better than these approaches.

For some tasks, it is desirable that a Day-of-Year slightly outside the year itself be handled acceptably.

Arithmetically

Transferred from other published and unpublished pages.

Generally, these methods start with March, and may count January as Month 13.

February is merely as long as is needed to pass the time until March.

Day-of-Year & Month-Length

Probably from "Astronomical Algorithms" (2nd ed, Dec '98) by Jean Meeus, Willmann-Bell Publishers, ISBN 0-943396-61-1.

K = 2 - (Y%4==0) // 2 - Leap, 1901-2099
N = Math.floor(275*M/9) - K*(M>2) + D - 30

N is the day-of-year of Y M D; extension to full Gregorian is obvious enough.

So for month-length :-

ML = Math.floor(275*(M+1)/9) - Math.floor(275*M/9) - K*(M==2)
// or
ML = M==2 ? 30-K : Math.floor(275*(M+1)/9) - Math.floor(275*M/9)

Month-Length

Tony Finch has noted that if (Month+10)*367%12 > 4 then Month (1..12) has 31 days :-

Similar methods are used in parts of JavaScript Date and Time 1 : Date Arithmetic and JavaScript Date and Time 3 : Input and Lengths.

Day-of-Year, after Zeller

From Week-Day, one can deduce the following for the number of days, N, since the end of February, and for the number of days, D, in each Month except February :-

    M := 1 + (Month+9) mod 12 ;
    N := 28*M + (13*M-1) div 5 - 30 + Day ;
    D := 30 + (3*M+2) div 5 - (3*M-1) div 5 ; // not for February

Other Forms

Other forms have been given which require floating-point arithmetic (beware rounding error; I would always prefer integer arithmetic) ; Michael Deckers has quoted the derived forms :-

  D = 1 + floor( ((M - 3) mod 12) * 30.6 + 0.4 )    // Mar 1 = 1 ?
  M = 1 + floor( (D + 60.6)/30.6 ) mod 12           // Mar   = 1 ?

Thence

  M = 1 + floor( (D*5 + 303)/153 ) // mod 12

and so

Gregorian Month Lengths

I have found the following way of calculating the lengths of the months :-

January is here also Month 13.

By Array Look-up

I have chosen to use a single array, though some tasks can be done faster with arrays of accumulated month-lengths.

Day-of-Year to Month and Day

Month and Day to Day-of-Year

Home Page
Mail: no HTML
© Dr J R Stockton, near London, UK.
All Rights Reserved.
These pages are tested mainly with Firefox and W3's Tidy.
This site, , is maintained by me.
Head.