Javascript dates and their manipulation

P

Peter Pfeiffer

I've written several scripts that have "while" blocks which increment a
date by one day if the date does not match one of a group of dates.
However, sometimes it apparently steps out out the while loop even
though my condition isn't met. Will work for a few loops then steps out
often.
Are there javascript "date" issues? I have also noticed different
results between Firefox and Internet Explorer.

thanks for any comments,

pj . . .
 
M

Michael Winter

[snip]
What your code apparently does is entirely secondary to what it actually
does, and that is most apparent when the code is present, or better
still, linked to at an example URL.

I'm sure that could be phrased far more simply. :)

[snip]
[...] one of the date guru's was here recently, musing over the
differences he was getting on a JS date function as operated across a
variety of UA's.

It should be noted that it was an arcane and unusual situation though,
[...]

Not so much unusual, but unspecified. The ECMAScript Standard doesn't
specify anything about the date formats an implementation should accept,
nor what format string-related methods should produce. The only
stipulation is that

d.valueOf() = Date.parse(d.toString()) = Date.parse(d.toUTCString())

That is, any string produced by an implementation should also be parsable.

It's reasonable to assume that certain standard formats should be
correctly interpreted, such as yyyy-mm-dd hh:mm:ss, but it's not
guaranteed by anything other than common sense.

[snip]

Mike
 
D

Dr John Stockton

JRS: In article <opsg52h2lzx13kvk@atlantis>, dated Mon, 8 Nov 2004
22:08:40, seen in Michael Winter <M.Winter@bl
ueyonder.co.invalid> posted :
It's reasonable to assume that certain standard formats should be
correctly interpreted, such as yyyy-mm-dd hh:mm:ss, but it's not
guaranteed by anything other than common sense.

Reasonable, maybe; but is it reasonable to assume that software will be
reasonable? You must know which company supplied most instances of
browsers; you must be aware of their country's traditional attitude
towards international standards.

For me, using IE4, new Date("2004-11-09 13:45:15") -> NaN
but new Date("2004/11/09 13:45:15") -> Tue Nov 9 13:45:15 UTC 2004
(in contexts calling for a string).
 
D

Dr John Stockton

JRS: In article <%[email protected]
et>, dated Mon, 8 Nov 2004 19:54:35, seen in
Peter Pfeiffer said:
I've written several scripts that have "while" blocks which increment a
date by one day if the date does not match one of a group of dates.
However, sometimes it apparently steps out out the while loop even
though my condition isn't met. Will work for a few loops then steps out
often.

That is probably because your code is incorrect. A common cause, but
not the only one, is assuming that there are 86400 seconds in every day.

If you had posted a complete, but brief, working "non-working example",
with explanation of intent and results, then probably we would have been
able to explain why it should have done what it did, and/or what should
have been written to make it do what had been hoped for.

Read the newsgroup FAQ.
 
M

Michael Winter

JRS: In article <opsg52h2lzx13kvk@atlantis>, dated Mon, 8 Nov 2004
22:08:40, seen in Michael Winter
It's reasonable to assume that certain standard formats should be
correctly interpreted, such as yyyy-mm-dd hh:mm:ss, but it's not
guaranteed by anything other than common sense.

Reasonable, maybe; but is it reasonable to assume that software will be
reasonable? [...]

Not at all. I did only say reasonable, and did add "not guaranteed". :)
You must know which company supplied most instances of browsers; you
must be aware of their country's traditional attitude towards
international standards.

Yes, unfortunately.

I suppose that the only thing guaranteed about strings and the Date object
is how unreliable they are and how it's probably best to avoid using them
together.

Mike
 
P

Peter Pfeiffer

Dr said:
JRS: In article <%[email protected]
et>, dated Mon, 8 Nov 2004 19:54:35, seen in


That is probably because your code is incorrect. A common cause, but
not the only one, is assuming that there are 86400 seconds in every day.

If you had posted a complete, but brief, working "non-working example",
with explanation of intent and results, then probably we would have been
able to explain why it should have done what it did, and/or what should
have been written to make it do what had been hoped for.

Read the newsgroup FAQ.
Thanks for the replies, didn't mean to remain silent so long.
I know some of these points. Missed the FAQ about posting examples
though. I've spent hours trying to figure out why some other code I
wrote works on PC and not on a Mac, so I thought I'd ask a general
question about the robustness of javascript.
Here are some functions I use:
// compares dates to see if they are the same day.
//(Only interested in local dates.)

function compareDates(date01, date02){
if(date01.getDate()!=date02.getDate()){
return false;
}else{
if(date01.getMonth()!=date02.getMonth()){
return false;
}else{
if(date01.getYear()!=date02.getYear()){
return false;
}else{
return true;
}
}
}
}


// Writes to document the due date for a loaned item, given the date,
// location, and loan period
// while loop is in this function

function printDueDate(mydate, branch_index, due){
xdayslater.setYear(mydate.getYear());
xdayslater.setMonth(mydate.getMonth());
xdayslater.setDate(mydate.getDate());
addDays(xdayslater, Loan_Periods[due] );

while(isBranchClosed(xdayslater, Branch_Names[branch_index]) ){
addDays(xdayslater, 1);
}
document.write( Month_Names[xdayslater.getMonth() ] + " " +
xdayslater.getDate() + ", "+ isBranchClosed( xdayslater, "DO") );
}


// Checks to see if the date falls on a holiday, or
// on a day that the branch is closed
// (Only one if statement for branch "ML" is shown.)

function isBranchClosed( date, branch) {
for(var i =0 ; i <Holidays.length; i++){
if( compareDates(date, Holidays))
return true;
}
if(branch=="ML" ){ // Could also be "DO"
for( var i=0; i < ML_days_closed.length; i++){
if(ML_days_closed==date.getDay()) return true;
}
return false;
}
}

Using these functions, a script in a web page writes a table of due
dates for a given location, range of days and several loan periods
(week, two week, etc..
Works well, except for a few places wwhere the due dates written are
days that the location is closed. The while loop should have iterated
one more day. See this page:
http://pjpf1.home.att.net/duedatetester_DO.html
Note the One Week loan days for the 18th and 19th are the 27th - which
is a weekend day where it is normally closed.

I dare to guess that the browser writing the table asynchronously, and
therefore possibly getting confused about the dates. But hopefully some
sharp eyes may find my bad code.

Thanks for helping in this problem.
pj . . .
 
D

Dr John Stockton

JRS: In article <opsg7vmdzgx13kvk@atlantis>, dated Tue, 9 Nov 2004
21:35:21, seen in Michael Winter <M.Winter@bl
ueyonder.co.invalid> posted :
I suppose that the only thing guaranteed about strings and the Date object
is how unreliable they are and how it's probably best to avoid using them
together.

I believe that the strings
YYYY/MM/DD hh:mm:ss
and YYYY/MM/DD hh:mm:ss GMT - or UTC
are always correctly interpreted;
and that, except perhaps for Americans, the date-to-string conversions
provided always include hh:mm:ss with hh = 00..23. Americans agree?

For me, all six combinations of YYYY Mon DD are understood. If present,
GMT does not have to be at the end, but I've not tried all 24
permutations.
 
D

Dr John Stockton

JRS: In article <[email protected]
..net>, dated Wed, 10 Nov 2004 04:23:20, seen in
news:comp.lang.javascript said:
// compares dates to see if they are the same day.
//(Only interested in local dates.)

Call it AreDatesSame, and the effect is more obvious.
function compareDates(date01, date02){
if(date01.getDate()!=date02.getDate()){
return false;
}else{
if(date01.getMonth()!=date02.getMonth()){
return false;
}else{
if(date01.getYear()!=date02.getYear()){
return false;
}else{
return true;
}
}
}
}

I think that this is equally effective :

function compareDates(date01, date02) {
return date01.getDate() == date02.getDate() &&
date01.getMonth() == date02.getMonth() &&
date01.getYear() == date02.getYear() }


Another approach would be to write a function (or method) to convert the
milliseconds UTC which is actually (it seems) stored to a local
daycount; your holiday table could be pre-converted in a single pass.

function LDC(D) {
return Math.floor( (+D + D.getTimezoneOffset()*6e5)/864e5 ) }

where the second + might need to be - . Test that.

function printDueDate(mydate, branch_index, due){
xdayslater.setYear(mydate.getYear());
xdayslater.setMonth(mydate.getMonth());
xdayslater.setDate(mydate.getDate());
addDays(xdayslater, Loan_Periods[due] );

while(isBranchClosed(xdayslater, Branch_Names[branch_index]) ){
addDays(xdayslater, 1);
}
document.write( Month_Names[xdayslater.getMonth() ] + " " +
xdayslater.getDate() + ", "+ isBranchClosed( xdayslater, "DO") );
}

There, xdayslater must be a Date Object of uncertain initial value; if
it happens to be the 31st of a month and setMonth calls for Sep Apr Jun
Nov, or the 31st, 30th, and probably 29th and setMonth calls for Feb,
then the result will not be as probably wanted.

One can do setFullYear(Y, M, D).

Better to declare xdayslater as local,

var xdayslater = new Date(0)

where the initialisation is fast /* (0) beats () */ and sets, throughout
the Old World, 1970-01-01 local. (It's actually wrong for the UK, since
we used GMT+1 on that date.)

var xdayslater = new Date(2e8)

should set a safe date everywhere; early Jan 1970.

BUT : If mydate is to be copied into a new Object,

datecopy = new Date(+mydate)

should be best.



ISTM that you have no interest in time of day. If you use setHours to
put a Date Object to noon, you can then gaily add and subtract multiples
of 864e5 without worrying about Summer Time changes, which then cannot
affect Y M D.

Functions such as addDays are frequently wrong, by ignoring Summer Time.

Works well, except for a few places wwhere the due dates written are
days that the location is closed. The while loop should have iterated
one more day. See this page:
http://pjpf1.home.att.net/duedatetester_DO.html

I read News off-line.
Note the One Week loan days for the 18th and 19th are the 27th - which
is a weekend day where it is normally closed.

You did not say what the month, or location, was; but from what you
posted here that *could* be a Summer Time problem.


I think that you would do best to convert your holiday table, which is
apparently used repeatedly, from YMD to a local integer daycount, and to
work entirely with daycounts. If your business does not get too near
the Date Line (AK & HI are safe; NZ etc. are not) then you can safely
convert daycount+0.5 to local date with the usual functions
with (new Date((dc+0.5)*864e5) ... getDate() ...
Otherwise, IIRC,
with (new Date(d*864e5) ... getUTCDate() ...


Note that it is sufficiently easy to convert Y M D to/from a daycount
without using Date Objects; it can also be faster : see in
<URL:http://www.merlyn.demon.co.uk/daycount.htm>
 
P

Peter Pfeiffer

Dr said:
JRS: In article <[email protected]
.net>, dated Wed, 10 Nov 2004 04:23:20, seen in
// compares dates to see if they are the same day.
//(Only interested in local dates.)


Call it AreDatesSame, and the effect is more obvious.

function compareDates(date01, date02){
if(date01.getDate()!=date02.getDate()){
return false;
}else{
if(date01.getMonth()!=date02.getMonth()){
return false;
}else{
if(date01.getYear()!=date02.getYear()){
return false;
}else{
return true;
}
}
}
}


I think that this is equally effective :

function compareDates(date01, date02) {
return date01.getDate() == date02.getDate() &&
date01.getMonth() == date02.getMonth() &&
date01.getYear() == date02.getYear() }


Another approach would be to write a function (or method) to convert the
milliseconds UTC which is actually (it seems) stored to a local
daycount; your holiday table could be pre-converted in a single pass.

function LDC(D) {
return Math.floor( (+D + D.getTimezoneOffset()*6e5)/864e5 ) }

where the second + might need to be - . Test that.


function printDueDate(mydate, branch_index, due){
xdayslater.setYear(mydate.getYear());
xdayslater.setMonth(mydate.getMonth());
xdayslater.setDate(mydate.getDate());
addDays(xdayslater, Loan_Periods[due] );

while(isBranchClosed(xdayslater, Branch_Names[branch_index]) ){
addDays(xdayslater, 1);
}
document.write( Month_Names[xdayslater.getMonth() ] + " " +
xdayslater.getDate() + ", "+ isBranchClosed( xdayslater, "DO") );
}


There, xdayslater must be a Date Object of uncertain initial value; if
it happens to be the 31st of a month and setMonth calls for Sep Apr Jun
Nov, or the 31st, 30th, and probably 29th and setMonth calls for Feb,
then the result will not be as probably wanted.

One can do setFullYear(Y, M, D).

Better to declare xdayslater as local,

var xdayslater = new Date(0)

I declare it like this:
xdayslater = new Date(); at the beginning of the script.
where the initialisation is fast /* (0) beats () */ and sets, throughout
the Old World, 1970-01-01 local. (It's actually wrong for the UK, since
we used GMT+1 on that date.)

var xdayslater = new Date(2e8)

should set a safe date everywhere; early Jan 1970.

BUT : If mydate is to be copied into a new Object,

datecopy = new Date(+mydate)

should be best.



ISTM that you have no interest in time of day. If you use setHours to
put a Date Object to noon, you can then gaily add and subtract multiples
of 864e5 without worrying about Summer Time changes, which then cannot
affect Y M D.

Might try that. In geberal, I was trying to keep it simple. I'm not a
javascript pro.
Functions such as addDays are frequently wrong, by ignoring Summer Time.
It's happening in "Winter time" for sure, haven't seen problems in
Summer Time.
I read News off-line.




You did not say what the month, or location, was; but from what you
posted here that *could* be a Summer Time problem.
I think that you would do best to convert your holiday table, which is
apparently used repeatedly, from YMD to a local integer daycount, and to
work entirely with daycounts.
Not familar with daycounts. Can you explain? While debugging, I did a
listing of the date and whether it was a closed or open day and that
passed the test. My omission of pre-calculated open/closed data was a
habit picked up from Java coding - where some data is dynamic.


thaqnks,

pj . . .
 
D

Dr John Stockton

JRS: In article <[email protected]
, dated Thu, 11 Nov 2004 00:30:26, seen in news:comp.lang.javascript,
Peter Pfeiffer <[email protected]> posted :

(please do not over-/full- quote)
Not familar with daycounts. Can you explain?

See in <URL:http://www.merlyn.demon.co.uk/daycount.htm>,
and in <URL:http://www.merlyn.demon.co.uk/dayscale.htm>.

Some particular day is selected as Day 1.
The next day is Day 2, then Days 3, 4, 5, ... follow ;
the previous day is Day 0, preceded by -1, -2, etc.
Sometimes a Day 0 is chosen as the starting point.

The beginning of the present millennium, 2001-01-01, is a good choice
for Day Zero because, being a Monday, it also begins the standard week
(except for Americans). The beginning of the first Gregorian millennium
is also good.

In javascript, 1970-01-01 Thu is an obvious choice.

* JD 0 starts BC 4713-01-01 12:00:00 GMT (Julian)
* CJD 0 is BC 4713-01-01 local time (Julian; 4714-11-24 Gregorian)
* MJD 0 is AD 1858-11-17 GMT
* CMJD 0 is AD 1858-11-17 local time.

It is best to choose a zero date which precedes any dates of interest.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,679
Members
48,796
Latest member
Greg L.

Latest Threads

Top