See also in Field Rollover.
Date methods can be slow, so be careful not to repeatedly recalculate anything that can be remembered.
This shows generation of a Date Object set by UTC literals and generation of a Date Object representing UTC YMDhms from a Date Object value representing the same civil YMDhms :-
It can be quicker to use, instead of Date Objects, algorithms using efficient Day Count conversion routines; this is done in some of Week Number Calculation.
Normally, a Date Object will always be created with a particular value required : "now", or given by parameters.
Otherwise, for N being numeric, new Date(N) should be faster than new Date() since, while both create an Object, the former only needs to load it with N while the latter must consult the system clock and maybe the locality settings. Moreover, with the former, the value is reproducible. So, unless the current date/time is needed, the former is better.
Obj = new Date() // if "now" is needed Obj = new Date(0) // otherwise better
To load UTC YMD into a Date Object, use, as above :-
Obj = new Date(Date.UTC(Y, M-1, D)) // also h m s ms
To copy or clone a Date Object D1 consider :-
D2 = new Date(+D1) or D2 = new Date(D1.valueOf())
in which the + calls for the transfer of a Number rather than allowing a String (properties other than the date/time will not be copied).
Remember to allow for possible Summer Time and Time Zone changes, except when using GMT/UTC. Much code presented elsewhere ignores these, and is therefore in error part of the time. If UTC functions can be used, the overheads and errors can be avoided.
Otherwise, if Days are specified, then work directly with Days, rather than with milliseconds from 1970, as civil days are not always 24 hours long, but can be 23 or 25 hours. Likewise, both Months and Years have varying numbers of Days. Always test over a Summer Time change.
Anything containing 1000*60*60*24 or 86400000 or 864e5 is suspect, unless it is used in conjunction with UTC functions or there is appropriate rounding or offset adjustment. Note that in general it will be the user's settings that matter; on the Web, Summer Time remains significant even for Polar and Equatorial authors.
Where that number is used, it is better written as 864e5 since that form is less prone to error.
The addition of 24 hours of actual time has advanced the EU civil time by only 23 hours; the inverse occurs in Spring.
Opera 10.51 has a peculiar problem.
SEE ALSO my Date and Day Count which is largely developed from Zeller's work.
Remember that a browser's local time is likely not to be GMT/UTC; so getTimezoneOffset may be needed.
Parts of this uses similar methods to those of The Calendrical Works of Rektor Chr. Zeller : The Day-of-Week and Easter and Date and Day Count.
Given a Date Object, divide by 864e5 and take the integer part.
Given a Date Object (or string), go to 0000h GMT and divide; or work with the internal value of a Date Object.
Note that new Date(D) where D is a Date Object is not reliable for years before A.D. 100. If D is known to be a Date Object, use +D which will also often be quicker.
For differencing, Standard Time Zone (but not offset change) can be ignored. The UNIX Epoch date is a Thursday; adding three to put the base at the start of a week can be useful.
Tests - all days in :
Use Back to return.
Lines should end 0 0 1.
Again, remember Summer Time and Time Zone; days are not all the same length. Do not attempt date shifting in time units, or month/year shifting in days; direct functions are provided.
Note : The clock change, Spring and Autumn, can occur on the 31st of the month; so, for example, 86400 seconds before April 1st can be late in March 30th (e.g. EU, one year in 7) instead of being the last day of March.
setFullYear(yearValue[, monthValue, dayValue]) setMonth(monthValue[, dayValue]) setDate(dayValue) setHours(hoursValue[, minutesValue, secondsValue, msValue]) setMinutes(minutesValue[, secondsValue, msValue]) setSeconds(secondsValue[, msValue]) setMilliseconds(msValue)
Use such as
which always give the present civil time tomorrow (strictly, there is one hour in Spring during which this is not possible, for places with Summer Time); as usual, month and year will be changed if necessary.
For tomorrow (maybe to see if today is the end of the month) :-
Note that incrementing/decrementing in Months can, in the first instance, get to the 29th, 30th or 31st of a month that does not have that date; in that case, the Object enters the following month, which may or may not be appropriate (see also 0: Date Object Information).
Starting with January 31st of successive years, that correctly gives for leap years Feb 29th, else Feb 28th. Similarly for altering the Year and avoiding a non-existent Feb 29th.
To step continuously along month-ends, step the beginnings of each following month, and go back one day each time.
Once more, remember Summer Time and Time Zone.
One must decide whether the difference is to use days each of 24 hours, or is to use days of local time.
Mere comparison is easy (apart from the autumnal ambiguous hour); compare the fields in order of diminishing significance, and return at the first difference; or use Date objects and compare their values.
To determine whether one date is within a given number of days of another, it may be easier or safer to increment/decrement one of the dates and then compare the result with the other date than it is to work by subtraction.
If Date Objects are provided, one must consider possible effects of their time components on comparisons.
Note : In Opera 9.2x, new Date("Y/M/D") gives NaN for Y after 9999.
See in datefmts for ISO 8601.
The above function is used in the code below.
For the difference of dates in days, set the local dates into date objects, subtract the values, divide by 864e5, and then round to integer; this should accommodate Summer Time transitions.
Alternatively, set the dates as GMT into date objects or use Date.UTC.
Depending on your definition of "between", perhaps increment or decrement the result.
A difference in days, whether or not accompanied by months and/or years, can readily be converted to weeks and days :- W = (D-(D%=7))/7 ; think about needs for D<0 . To reverse, D += 7*W .
Difference in Years, Months and Days is somewhat arbitrary, as years and months vary in length.
If avoidable (it may be needed for formal administrative purposes), do not attempt to subtract date/time in Y-M-D h:m:s; all that borrowing is tiresome and error-prone. Think about the exact requirements; check management expectations and needs. For people's ages, however, it seems often necessary to work in Y-M-D, with care.
Since there are always 12 months in a year, one can for simplicity work with M' = 12×Y+M; and for subtraction one can ignore month numbers being 1..12 rather than 0..11. Similarly, hh:mm:ss can be converted to seconds, if Summer Time transitions are ignored.
Frequently, either the initial or the final date will be fixed, and the other will be the current date.
A sequence of differences is obtained by keeping one date fixed and stepping the other date by one day at a time.
A sequence of differences should always look plausible. Requirements include :-
I doubt whether all of those can be achieved at once!
Consider Apr 4 to May 6 must be one month and two days; also May 4 to Jun 6. Step the start daily to May 4; 30 steps, as Apr has 30 days. Step the close daily to Jun 6; 31 steps, as May has 31 days. Thus there cannot be a 1:1 correspondence between the two sets of intermediate differences; there must be an omission or a repeat.
Consider Apr 4 to Jun 3; 1 month gets to May 4, then -4+31+3 = 30 days. Jun 3 back to Apr 4; 1 month gets to May 3, then +3+30-4 = 29 days. In the first case the "borrow" is of May, in the second it is of April.
First convert BC dates to astronomer's notation, in which years go ... -2 -1 0 +1 +2 ... ; and, if necessary, consider past calendar reforms. The following uses only Gregorian AD dates.
Convert the years and months to just months, and subtract. Subtract the dates; if negative, first "borrow" the length in days of an appropriate month, with allowance for its year if it is February. Convert months back to years and months.
Increasing Interval - Borrow from the month before the
moving date, as Feb 01 == Jan 32.
Decreasing Interval - Borrow from the month with the moving date, as Feb 00 == Jan 31.
Note that with inputs of 2001-03-01 & 2001-01-30 the result that DiffDateC gives is 0,1,-1 and one may wish to put a lower bound of 0 on the Days, or borrow two months.
Another way would be to determine the difference in days, divide by 365.25/12 or 365.2425/12 and round down to get integer months, after which the rest is simple.
However, that makes the effects of varying month- and year- lengths rather conspicuous.
This has some of the problems of Difference in Years, Months and Days.
It is tricky, in respect of February 29th :-
For the difference in years alone :-
Non-optimal code :-
Remember, though, Summer Time, and those born on February 29th.
Again, remember Summer Time and location.
One can subtract seconds; if negative, borrow a minute; then subtract minutes, etc.
If days, hours, minutes, seconds are needed, then set the start and finish date/times into a date object (new Date() creates an object for the current date/time), and take valueOf() for each, and subtract these to get the difference in milliseconds. If only times are given, use a dummy date, e.g. T = "12:34:56" ; D = new Date("1/1/70 "+T) , possibly appending UTC.
Or, for start and finish, multiply days by 24, add hours, multiply by 60, add minutes, multiply by 60, add seconds; and subtract.
After subtracting, use Mod & Div to convert to days .. seconds :-
a mod b = a % b a div b = Math.floor(a/b) = (a-(a%b))/b // may need Math.round Sec = ms div 1000 // ms = ms mod 1000 Min = Sec div 60 ; Sec = Sec mod 60 Hr = Min div 60 ; Min = Min mod 60 Days = Hr div 24 ; Hr = Hr mod 24
It normally does not make a great deal of sense to convert time differences from days to months and years, which are of variable lengths.