© J R Stockton, ≥ 2009-09-16

Links within this site :-

**Merlyn Home Page**- Site Index, E-Mail, Copying**This Page**:-- Week Number to/from DayCount
- Day Counts - JD, MJD, CJD, CMJD, ...
- Date and Time Scales
- Zeller's Formulae
- JavaScript Date and Time Introduction
- VBScript Date and Time
- Included Functions
- For more date/time pages, and links, see Date and Time Index and Links

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.

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.*

- JDN 0.0 is Julian B.C. 4713 January 1st 12:00:00 GMT, a Monday.
- MJD 0.0 is Gregorian A.D. 1858 November 17th 00:00:00 GMT, a Wednesday.
`MJD = JDN - 2400000.5`

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.

- CJD 0.0 is Julian B.C. 4713 January 1st 00:00:00 local.
- CMJD 0.0 is Gregorian A.D. 1858 November 17th 00:00:00 local.
`CMJD = CJD - 2400001`

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.

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.

- I often use CMJD
- A zero date of A.D. 0000-03-01 can be arithmetically convenient
- Beware of errors when using
*div*or*mod*with a negative argument - So, for earlier dates, set the origin back by a multiple of 400 (or 28) years

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.

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.

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.*

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.

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.

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.

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, 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.

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.

Two versions, essentially the same :

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.

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

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

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

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

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

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

These two functions each test a function below.

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

This has a straightforward way of determining the year :-

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` :-

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.

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

See in my VBScript Date and Time 1.

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.

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.

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)

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.

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 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

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

January is here also Month 13.

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