FAQ Topic - How do I format a date with javascript? (2009-06-01)

G

Garrett Smith

Dr said:
In comp.lang.javascript message <[email protected]
september.org>, Thu, 11 Jun 2009 14:44:38, Garrett Smith
[...]
Try to understand that the "user" is not calling this code

It is the user who is executing the page. A Web page without users is
of no use.

The code is not directly related to UI, web page, form.

Code that interacts with the UI is a different problem that should be
decoupled from parsing or formatting.

This problem is about formatting a date, and now parsing a string.

These two things should not coupled.
Of course, parsing a format and parsing a date string are not the same
thing.

"A local date string in extended ISO 8601 format <ICODE>YYYY-MM-
DD</ICODE> can be read to a Date Object with the following :-"

Does that explain it any better?

By Farlex, Inc. One sees in it what one expects to find in American
dictionaries.

A useful definition.

It is a concern to avoid using terminology which could be
misinterpreted, however, it does not seem to be a problem to use
"international" here to mean: "transcending national boundaries or
viewpoints".

The BBC online dictionary is coded in a way that it requires javascript
to submit the form. This does not work in Firefox running NoScript.

The BBC provides a useful example of what not to do.
Dates are your area of expertise and your reviews are helpful. Please
do comment on the revised version.

That reminds me of a Wagner joke, which Google seems not to know.

[...]


It might be well just to always add 400 to the year and subtract 4800
months; the loss of 400 years up to & including Sep 12 275760 cannot be
of great immediate importance.

Your responses are finding less problem with the code example.

I will be uploading the revised edition soon.

Below:-
4.1 How do I write and read a date with javascript?

ISO 8601 Extended formats can be understood internationally, without
ambiguity.

A local Date object where year >= 0 can be formatted to a common ISO
8601 format YYYY-MM-DD with:-

/** Formats a Date to YYYY-MM-DD (local time), compatible with both
* ISO 8601 and ISO/IEC 9075-2:2003 (E) (SQL 'date' type).
* @param {Date} dateInRange year 0000 to 9999.
* @throws {Error} if the year is < 0.
*/
function formatDate(dateInRange) {
var year = dateInRange.getFullYear(),
isInRange = year > 0 && year < 9999,
yyyy, mm, dd;
if(!isInRange ) {
throw Error("formatDate: year must be 0000-9999");
}
yyyy = padLeft(year, 4, "0");
mm = padLeft(dateInRange.getMonth() + 1, 2, "0");
dd = padLeft(dateInRange.getDate(), 2, "0");
return yyyy + "-" + mm + "-" + dd;
}

/**
* @param {string} input: input value converted to string.
* @param {number} size: desired length of output.
* @param {string} ch: single character to prefix to s.
*/
function padLeft(input, size, ch) {
var s = input + "";
while (s.length < size) {
s = ch + s;
}
return s;
}

Never use a local date/time format for a non-local event. Instead, use
UTC, as in ISO 8601 YYYY-MM-DDThh:mm:ssZ ( Z is the only letter suffix).

The T may be omitted where doing so would not cause ambiguity. For an
SQL date, it must be replaced by a single space.

For a local date/time with time offset, to unambiguously indicate a
particular instant, use ISO 8601 format YYYY-MM-DDThh:mm:ss±hh:mm.

An Extended ISO 8601 local Date format YYYY-MM-DD can be parsed to a
Date with the following:-

/**Parses string formatted as YYYY-MM-DD to a Date object.
* If the supplied string does not match the format, an
* invalid Date (value NaN) is returned.
* @param {string} dateStringInRange format YYYY-MM-DD, with year in
* range of 0000-9999, inclusive.
* @return {Date} Native Date object representing the string.
*/
function parseISO8601( dateStringInRange ) {
var date = new Date(NaN),
isoExp, parts;
isoExp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/;
parts = isoExp.exec(dateStringInRange);

if(parts) {
date.setFullYear(parts[1], parts[2] - 1, parts[3], 0, 0, 0, 0);
if(parts[2] != date.getDate()
|| parts[1] != date.getMonth() + 1
|| parts[0] != date.getFullYear() ) {
date.setFullYear(NaN);
}
}
return date;
}

* ECMA-262 Date.prototype, s. 15.9
* http://en.wikipedia.org/wiki/ISO_8601
* ISO 8601:2004(E)
* http://www.merlyn.demon.co.uk/js-date9.htm

=====================================================================

Other comments and suggestions are welcome.

Some readers may have noticed that the daily posts code examples are not
properly indented. I will fix that next. Also on the agenda: The new Notes.

Garrett
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Fri, 12 Jun 2009 01:14:07, Garrett Smith
The entry:

"11.1 How do I get my browser to report javascript errors?"

covers the subject of browsers reporting errors.

But it says nothing about the effect of calling throw.


I do not know KDF9, but "throw" is a basic computer science term nowadays.

Of course; but there are still two different types of throw call in the
Standard; the reserved word, and the action internal to failing
routines. a (CtrlF-type) search cannot distinguish. If the reserved
word had been thro, raise, abort, etc., the clash would not have
occurred. It's like the difficulty in talking about undefined results
in a context where "undefined" can mean an Object type, the value of an
object of that type, or its literal representation in code.

No! The alert method has no place in such code. Calling alert there
would be a bad side effect. It would be awkward for the caller to
handle that gracefully. Consider:-

var realAlert = window.alert;
window.alert = logError;
formatDate( myDate );
window.alert = realAlert;

That is awful.

Anyone who redefines something provided by the system must look to see
whether that object is used elsewhere in the code.

Anyone taking code from a FAQ should read it first, and should test it
before embedding it deeply in other code. Writing alert(string) is a
concise and reliable way both of indicating a problem on initial test
and showing where other error handling might be substituted. Just
quitting is not satisfactory. Returning a string such as "Year error"
instead of a YYYY-MM-DD string also works; it will be noticed.

In production code, the error should never be allowed to occur.

The return value of Date.prototype.toString itself is implementation-
dependent and that is stated in the specification which is linked.

It is, for non-NAN objects, always a readable representation of the
date; the result for NaN varies more than that.


You are not remembering what a FAQ for a general language newsgroup
should be like. You presume too much knowledge of the language. The
FAQ should be aimed at the needs of those who wander in from time to
time with a serious but ill-expressed question and are promptly driven
out again by the Great Bully.

It's like a "Null Object".

It must not be called that, though.


Taking all of the suggestions, the new draft follows:-

================================================================
4.1 How do I write and read a date with javascript?

The ISO 8601 Extended format can be understood internationally, without
xxx ^An (there are more than one) (don't use Any[0])
world-wide ---> xxxxxxxxxxxxxx

ISO 8601 Extended formats can be...

No; that definitely implies that all of them can be.
or

[Most|Common|Many] 8601 Extended formats can be...

or even

Many common ISO 8601 Extended formats can be..

Obvious minor variations such as year outside 0000-9999 and the presence
of time fields apart, there are not enough extended formats to justify
"Many".


Look at the return statement:-

| return yyyy + "-" + mm + "-" + dd;

The intent of the code and code is doing could not be any clearer.

Yes, but that would still apply if year & yyyy were replaced by Y, mm by
M, dd by D. The comment must say that the output is YYYY-MM-DD, which
makes all else obvious.


Don't those two words mean the same thing?

No. A suffix is below, an index or superfix above - as in HTML <sub>
<sup>. A prefix is before, a postfix is after, both on-the-line.
Suffix in this context will be understood, but postfix is correct.


By what, a user-defined one? That would break it.

Not if it had all the necessary methods etc., just with changes
elsewhere. "Native" is not needed, and not guaranteed.
if(parts) {
date.setFullYear(parts[1], parts[2] - 1, parts[3]);
date.setHours(0,0,0,0);
With new Date(NaN), setFullYear cannot avoid setting the "local time
part"; therefore, setHours may not now be essential.

Good.

I only wrote "may not be".


The RegExp is not acceptable. It partly but incompletely validates
the
date. The date should be either tested for character pattern or not so
tested; and it should either be fully numerically validated or not
numerically validated at all.
Again, the answers are all in the archives[1], and Thomas seems to
be
slipping since AFAIR he has not told you that.
Test the pattern for, at the very minimum,
/^\D*\d+\D+\d+\D+\d{1,2} then non-digit or end/.
Apply the three fields as above into new Date,
check the Month of the date object agrees with the second numeric field.

It occurred to me to validate that by calling the relevant date methods
but I did not attach much significance to it and considered the
function could return an adjusted date (from MakeDay), should the
caller pass a February 29 on a non-leap year, for example.

It is abominable to do that for one breach of Gregorian notation but not
for others. Month=13 is just as valid as February 31st.

In fact, there should be two versions of the read routine; one for when
the string is guaranteed in field order and Y M D being good (there is
no need to require a specific separator or number of digits), and one
which validates the numbers. There is no necessary need to validate the
pattern or punctuation to a greater extent than the rest of the code
needs.
If validation is the way to go, the parts should be checked in order
from most to least likely to fail. That is the days, then months, then
years. By doing this, failure is reached faster.

No. Most inputs will pass validation, so the need is to reach success
fastest. That's not necessarily the same thing. Also, since dates
needing validation will generally be form entries, speed is not
important at modern clock rates.
If the validation is going to fail, it will have a greater chance of
failing sooner with a stricter regexp (a null match avoids method
calls):
/^\s*([\d]{4})-(0[1-9]|1[0-2])-([0-2][0-9]|(?:3[0|1]))\s*$/

But that passes Feb 31, which gives a date of Mar 2 or 3. And a long
RegExp is slower in operation.

We went into validation rather thoroughly before. Read the archives.
However, the simpler pattern posted earlier is easier to read and
perhaps more suitable for the FAQ.

The pattern should ignore leading and trailing whitespace only and not
try and find a date format buried in a string. \s is probably enough
here. I know that implementations are not consistent with each other or
the specification on \s and we have discussed the Mongolian vowel
separator and no-break space (\u00a0).

I wrote, legibly enough, "at the very minimum", in order to show only
what was needed for validation by checking getMonth to work. But why
not use \D, which correctly accepts ALL whitespace varieties and permits
finding dates in strings containing other non-digits? The purpose is to
validate the date indicated, not the ISO compliance.
Revised:-

/**Parses string formatted as YYYY-MM-DD to a Date object.
^a xxxxxxxxxxxx superfluous
* If the supplied string does not match the format, an xxxxxxxx superfluous
* invalid Date (value NaN) is returned.
* @param {string} dateStringInRange format YYYY-MM-DD, with year in
No need to specify the format twice, especially in a language delivered
as source.
* range of 0000-9999, inclusive.
* @return {Date} Native Date object representing the string.
*/
function parseISO8601( dateStringInRange ) {

Following your earlier argument, the function name should indicate which
ISO format type. InRange is superfluous.
var date = new Date(NaN),
isoExp, parts;
isoExp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/;

No general need to check field lengths, except for not exceeding DD.
parts = isoExp.exec(dateStringInRange);

if(parts) {
date.setFullYear(parts[1], parts[2] - 1, parts[3], 0, 0, 0, 0);

It seems unwise to use arguments that ECMA 3 & FD 5 specify are not
there. The length of setFullYear is 3 -
new Date().setFullYear.length gives 3.
if(parts[2] != date.getDate()
|| parts[1] != date.getMonth() + 1
|| parts[0] != date.getFullYear() ) {

You clearly have not understood. All this is in the archives, and on my
site. There is no need to test getDate, since if the value given is
outside the month but in 00-99 (guaranteed by RegExp) then the getMonth
test must fail. There is no need to test the Year either, since
setFullYear does not add 1900 to years under 100.
date.setFullYear(NaN);

setTime() seems nicer, since it only ever stuffs its clipped numeric
argument in the Object, whereas setFullYear() can do more. And it's
easier to see from the standard what an argument of NaN must do.
}
}
return date;
}


And more liberal than the one I provided.

As explained.


It looks like Date2[2] handles parsing and setting of various ISO 8601
formats.


AFAIR, not "various"; it handles all of the date and date/time formats,
but not the interval or duration ones.
I think is more complicated than the example would need. While you have
some good ideas, I find function names like ZBDoCY to be unmemorable
and confusing.

Zero-Based Day of Calendar Year; in other words, Ordinal Date minus one.

But that's within a routine, not part of the user interface. It's only
ever assigned near the end of a routine and only ever used in the next
statement, followed by a return that does not use it.

Google finds it, but not Google Maps; so it won't get confused with a
place in Eastern Europe.

Note also that Date2 is a proposal for implementation as a new native
Object, so the JavaScript would then be converted to compiled code in,
possibly, C++.
[0] Unwise to claim that ISO Week Numbering will be understood in NA.

What is NA?

Context-dependent; Namibia, or North America (give or take Mexico and
the 20 others). Wikipedia knows it. Often, rightly or wrongly, used
for US+CA.


Inadequately written : the page implies that YYYY-MM-DD is the only ISO
date format. Ignoring extensions and truncations and compressions,
there are two others. It links to <http://www.w3.org/International/ques
tions/qa-date-format> which is also unworthy : it says "The format
MM/DD/YY is unique to the United States." which alas is not true. I
suspect it's common in the Northern Sidekick, and likely to be used in
places that don't natively use English.
 
G

Garrett Smith

Dr said:
In comp.lang.javascript message <[email protected]
september.org>, Fri, 12 Jun 2009 01:14:07, Garrett Smith






But it says nothing about the effect of calling throw.

Technically, |throw| is a Statement, and is not called.

Exception handling could find its place in the FAQ.
Of course; but there are still two different types of throw call in the
Standard; the reserved word, and the action internal to failing
routines. a (CtrlF-type) search cannot distinguish. If the reserved
word had been thro, raise, abort, etc., the clash would not have
occurred. It's like the difficulty in talking about undefined results
in a context where "undefined" can mean an Object type, the value of an
object of that type, or its literal representation in code.

Throw is a flow-of-control behavior. Whether it happens by intent of the
program or by accident does not change that.
Anyone who redefines something provided by the system must look to see
whether that object is used elsewhere in the code.

My point was that that would be the only way to "catch" an |alert|. An
error can be caught by standard exception handling mechanism.
Anyone taking code from a FAQ should read it first, and should test it
before embedding it deeply in other code. Writing alert(string) is a
concise and reliable way both of indicating a problem on initial test
and showing where other error handling might be substituted. Just
quitting is not satisfactory. Returning a string such as "Year error"
instead of a YYYY-MM-DD string also works; it will be noticed.

It would also be noticed to return "". Not an ISO-8601 format, but
noticeable.
In production code, the error should never be allowed to occur.

Absolutely not. It should be checked.
It is, for non-NAN objects, always a readable representation of the
date; the result for NaN varies more than that.

The result is specified as being implementation-dependent. The format
varies between implementations.

[...]
It's like a "Null Object".

It must not be called that, though.


The ISO 8601 Extended format can be understood internationally, without
xxx ^An (there are more than one) (don't use Any[0])
world-wide ---> xxxxxxxxxxxxxx
ISO 8601 Extended formats can be...

No; that definitely implies that all of them can be.
or

[Most|Common|Many] 8601 Extended formats can be...

or even

Many common ISO 8601 Extended formats can be..

Obvious minor variations such as year outside 0000-9999 and the presence
of time fields apart, there are not enough extended formats to justify
"Many".

So going with "Common ISO 8601 Extended formats..."

[...]
Yes, but that would still apply if year & yyyy were replaced by Y, mm by
M, dd by D. The comment must say that the output is YYYY-MM-DD, which
makes all else obvious.

I think the yyyy variable makes the code a little easier to read. I
don't find it hard to read:-

return year + "-" + mm + "-" + dd;

- but I do find it clearer as:-

yyyy + "-" + mm + "-" + dd;

- which does not change |year| to be a string.
No. A suffix is below, an index or superfix above - as in HTML <sub>

that's subscript.

superscript.

A prefix is before, a postfix is after, both on-the-line.
Suffix in this context will be understood, but postfix is correct.

[...]


We went into validation rather thoroughly before. Read the archives.
OK.
However, the simpler pattern posted earlier is easier to read and
perhaps more suitable for the FAQ.

The pattern should ignore leading and trailing whitespace only and not
try and find a date format buried in a string. \s is probably enough
here. I know that implementations are not consistent with each other or
the specification on \s and we have discussed the Mongolian vowel
separator and no-break space (\u00a0).

I wrote, legibly enough, "at the very minimum", in order to show only
what was needed for validation by checking getMonth to work. But why
not use \D, which correctly accepts ALL whitespace varieties and permits
finding dates in strings containing other non-digits? The purpose is to
validate the date indicated, not the ISO compliance.

It expands the functionality of what the method does to something it is
not designed or tested for. I don't want the method to guaranteed that.
Allowing leading/trailing space only keeps it simpler.

Including "\D" would match: YYYY-MM-DDT and the function would not do
anything with anything following that "T".
^a xxxxxxxxxxxx superfluous
No need to specify the format twice, especially in a language delivered
as source.

Following your earlier argument, the function name should indicate which
ISO format type. InRange is superfluous.

The "inRange" was to indicate that there is a range. That range is not
indicated, but it is 0000-9999.

Do you have in mind a better name for the function that would indicate
that?


formatDateToExtendedYYYYMMDD
- hard to read with all the long run of upper case letters. Even with
camelCase, it is an eyesore: formatDateToExtendedYyyyMmDd.

Underscore could possibly work:
formatDateToYYYY_MM_DD

- hard to read and does not indicate range.
var date = new Date(NaN),
isoExp, parts;
isoExp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/;

No general need to check field lengths, except for not exceeding DD.

The pattern is YYYY-MM-DD, and that is what the regexp checks (and
allows whitespace on the ends).
parts = isoExp.exec(dateStringInRange);

if(parts) {
date.setFullYear(parts[1], parts[2] - 1, parts[3], 0, 0, 0, 0);

It seems unwise to use arguments that ECMA 3 & FD 5 specify are not
Right.

there. The length of setFullYear is 3 -
new Date().setFullYear.length gives 3.
if(parts[2] != date.getDate()
|| parts[1] != date.getMonth() + 1
|| parts[0] != date.getFullYear() ) {

You clearly have not understood. All this is in the archives, and on my
site. There is no need to test getDate, since if the value given is
outside the month but in 00-99 (guaranteed by RegExp) then the getMonth
test must fail. There is no need to test the Year either, since
setFullYear does not add 1900 to years under 100.

Checking getMonth is all that is needed. Simpler and faster.

function parseISO8601( dateStringInRange ) {
var date = new Date(NaN),
isoExp, parts;
isoExp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/;
parts = isoExp.exec(dateStringInRange);

if(parts) {
date.setFullYear(parts[1], parts[2] - 1, parts[3]);
if( parts[1] != date.getMonth() + 1 ) {
date.setTime(NaN);
} else {
date.setHours(0, 0, 0, 0);
}
}
return date;
}

Garrett
 
M

Michael J. Ryan

Anyone relying on the first release of any software is a fool; any
browser not accepting "2009/01/20" correctly on or after the second
release should never be trusted, because five major browsers accept it
(and I've never known them not to).

What I don't get is why "2009-01-20" (iso-style formatting) is an invalid new
Date(), but a replace of /\-/g with '\\' is easy enough.
 
T

Thomas 'PointedEars' Lahn

Dr said:
Garrett Smith posted:

But it says nothing about the effect of calling throw.

`throw' is the keyword of a statement, but not of a call.


PointedEars
 
G

Garrett Smith

Michael said:
What I don't get is why "2009-01-20" (iso-style formatting) is an
invalid new Date(), but a replace of /\-/g with '\\' is easy enough.

ECMA 262 r3 preceedes ISO 8601:2000 and ISO 8601:2004(E).

Why have implementations chosen not to implement that is may be due to
the vast number of formats in ISO 8601.

TG 39 groups that is developing the ECMA 262 standard is producing
ECMAScript 5 (4 was dropped). ECMAScript 5 defines native Date methods
for parsing and formatting ISO 8601 formats.

If an implementation (say Spidermonkey) decided to implement a
non-standard extensions to the Date constructor the Date methods in a
way that it was capable of parsing YYYY-MM-DD, then which other ISO 8601
formats should it take? Should it stop there?

ISO 8601:2004(E) which includes ranges, UTC Designator, timezone offset,
week numbers.

This may have overwhelmed an implementor to the point where they would
decide not to casually implement YYYY-MM-DD and wait for the TG 39
committee to define a standard. I do not know if this is actually what
happened, but it seems possible.

The FAQ's formatDate is the arguably most human-readable format and is
the one format that is recommended by the w3c[1].

Some of the ISO 8601 Extended formats are for human consumption. Others
are a little harder on the eyes. The basic formats are hard to read.
Even with YYYY-MM-DD there is room to consider the allowed range for the
year. Should it be > 0, >= 0, > 1582?

The ECMAScript 5 recognizes only with one format which is intended
primarily for use with JSON. The TG 39 committee does not consider human
consumption for ISO 8601 and Allen has even gone as far as to state that
ISO 8601 is not intended for human consumption[2].

The TG 39 committee seems to have overlooked the value of other ISO 8601
formats.

I do not know if there are any studies done on human readers, but it
would beneficial to see a little research and investigation of the more
human-readable ISO 8601 formats and how readily and accurately they are
interpreted. Such study would include individuals of various locales and
varying ages and backgrounds.

If ES5 does not get more configurability, then it is not hard to parse
the common date format YYYY-MM-DD out of the current draft's design of
toISOString(), by taking a substring up to "T".

Garrett

[1]http://www.w3.org/QA/Tips/iso-date
[2]https://mail.mozilla.org/pipermail/es-discuss/2009-June/009495.html
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]>, Sat,
13 Jun 2009 15:11:43 said:
`throw' is the keyword of a statement, but not of a call.

"Mummy, what is that man for?"

Granted, it's now known that he (the probable original "he") did, in
1874, an act which later proved exceptionally valuable. Luke 10,37,end.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Fri, 12 Jun 2009 23:25:04, Michael J. Ryan
What I don't get is why "2009-01-20" (iso-style formatting) is an
invalid new Date(), but a replace of /\-/g with '\\' is easy enough.

With "/" "/".


One cannot expect Americans to consider international standards,
especially ones only seven years old. ISO 8601 appeared in 1988,
JavaScript in the USA in 1995. They did not even provide for DD/MM/YYYY
& DD.MM.YYYY, used in so many countries.

Remember : in implementing getYear(), they failed to consider
sufficiently that the 1900's had only half a decade to run, even though
corresponding events had occurred twice before in their country.

But they're not all bad - remember J Jerome.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Fri, 12 Jun 2009 17:30:12, Garrett Smith
Technically, |throw| is a Statement, and is not called.

Exception handling could find its place in the FAQ.

It would also be noticed to return "". Not an ISO-8601 format, but
noticeable.

But sometimes easy to miss. Consider a Table in which there is a column
of dates some of which are, for other reasons, not present. An empty
string does not look like a string, when written.


The ISO 8601 Extended format can be understood internationally, without
xxx ^An (there are more than one) (don't use Any[0])
world-wide ---> xxxxxxxxxxxxxx
ISO 8601 Extended formats can be...
No; that definitely implies that all of them can be.
or

[Most|Common|Many] 8601 Extended formats can be...

or even

Many common ISO 8601 Extended formats can be..
Obvious minor variations such as year outside 0000-9999 and the
presence
of time fields apart, there are not enough extended formats to justify
"Many".

So going with "Common ISO 8601 Extended formats..."

To be convincing, you will need to explain here which common ones fit
the rest of what you say. In the FAQ context, one needs something
stronger than "in each country, there will be some who understand".
Take today's date in the various ISO extended formats to different young
shop assistants, asking what's that? Probably, "YYYY-MM-DD" will be
recognised as a funny way of writing the date; the others may well be
considered as some strange sort of part number.




that's subscript.

superscript.

Yes. I wrote what I meant to write; there's a read error. There's no
semantic difference in this context in English between "fix" and
"script".

A prefix is before, a postfix is after, both on-the-line.



It expands the functionality of what the method does to something it is
not designed or tested for. I don't want the method to guaranteed that.
Allowing leading/trailing space only keeps it simpler.

You need to learn to write English so that it can be unambiguously
parsed by others. That can be read as either of
Allowing (leading/trailing space only) keeps it simpler.
Allowing leading/trailing space (only keeps it simpler).

Including "\D" would match: YYYY-MM-DDT and the function would not do
anything with anything following that "T".

That's right. But, at the ends of YYYY-MM-DD, it should be \D* . One
wants to reject a digit in that end position; there is no need to reject
anything else.
The "inRange" was to indicate that there is a range. That range is not
indicated, but it is 0000-9999.

Do you have in mind a better name for the function that would indicate
that?

Str. It is expected to be a string; it is only hoped that it will
represent a good date.
formatDateToExtendedYYYYMMDD
- hard to read with all the long run of upper case letters. Even with
camelCase, it is an eyesore: formatDateToExtendedYyyyMmDd.

Underscore could possibly work:
formatDateToYYYY_MM_DD

- hard to read and does not indicate range.

Call it YYYY_MM_DD.
var date = new Date(NaN),
isoExp, parts;
isoExp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/;
No general need to check field lengths, except for not exceeding DD.

The pattern is YYYY-MM-DD, and that is what the regexp checks (and
allows whitespace on the ends).

One needs to consider whether the code should check that the string is a
correct production of the ISO rules or should check that a valid date is
represented more-or-less in the ISO manner. For typed input, there's no
need to enforce rigour in the separators; "YYYY-MM-DD" is ISO but it's
easier to type "YYYY MM DD".

In fact the RegExp should be considered as an argument to the process of
typing the function.

function parseISO8601( dateStringInRange ) {
var date = new Date(NaN),
isoExp, parts;
isoExp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/;
parts = isoExp.exec(dateStringInRange);

if(parts) {
^
That looks like a call of the function 'if'. Goodman uses a space.
Flanagan uses a space.
date.setFullYear(parts[1], parts[2] - 1, parts[3]);
if( parts[1] != date.getMonth() + 1 ) {
date.setTime(NaN);
} else {
date.setHours(0, 0, 0, 0);
}
}
return date;
}

There's little point in reviewing untested code, as that obviously is.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Sat, 13 Jun 2009 09:58:24, Garrett Smith
ECMA 262 r3 preceedes ISO 8601:2000 and ISO 8601:2004(E).

And they clearly state that ISO 8601 first came out in 1988, which is
before JavaScript. 2004 is the 3rd edition. They also imply that
earlier ISO standards favoured Y M D order. Real Americans disdain
standards, especially non-American ones.
Why have implementations chosen not to implement that is may be due to
the vast number of formats in ISO 8601.

There are only two ISO 8601 formats for Gregorian dates in AD 0000-9999;
YYYYMMDD and YYYY-MM-DD. Browsers handle YYYY/MM/DD, and it's easy to
convert those to that (not necessarily optimal, of course).

TG 39 groups that is developing the ECMA 262 standard is producing
ECMAScript 5 (4 was dropped). ECMAScript 5 defines native Date methods
for parsing and formatting ISO 8601 formats.

In an extremely limited manner. They are really only addressing the
JSON formats. And it's not entirely too late to hope that the "Final
Draft" will be followed by a better one.
If an implementation (say Spidermonkey) decided to implement a non-
standard extensions to the Date constructor the Date methods in a way
that it was capable of parsing YYYY-MM-DD, then which other ISO 8601
formats should it take? Should it stop there?

ISO 8601:2004(E) which includes ranges, UTC Designator, timezone
offset, week numbers.

All of the formats that fully specify a date are useful. And it's not
too difficult to code for them all in JavaScript; therefore it could be
easily enough done in whatever the JavaScript engine is written in - as
long as no-one copies MS DatePart. However, YYYY-MM-DD will be
commonest; start there.

A Date Object cannot properly handle ISO interval or duration; it
contains only a Double of milliseconds from an Epoch.


Some of the ISO 8601 Extended formats are for human consumption. Others
are a little harder on the eyes. The basic formats are hard to read.
Even with YYYY-MM-DD there is room to consider the allowed range for
the year. Should it be > 0, >= 0, > 1582?

Why 1582? Proleptic Gregorian is often enough wanted, and few places
changed calendar in 1582. You'll be wanting the Swedish Calendar next;
and, for the Russian marker, Orthodox Easter.

The ECMAScript 5 recognizes only with one format which is intended
primarily for use with JSON. The TG 39 committee does not consider
human consumption for ISO 8601 and Allen has even gone as far as to
state that ISO 8601 is not intended for human consumption[2].

That's his view. It is not supported by ISO 8601, which is for
information interchange and does not reject human participation. Some
formats are more suitable for human use, others more for machine use. I
use both YYYY-MM-DD and YYYYMMDD when writing with pen and ink,
depending on who is expected to read it.

The reasons why YYYY-MM-DD is best for machine use are equally valid for
human use; it's better than DD/MM/YYYY or the absurd MM/DD/YYYY.
 
G

Garrett Smith

Dr said:
In comp.lang.javascript message <[email protected]
september.org>, Fri, 12 Jun 2009 17:30:12, Garrett Smith


But sometimes easy to miss.

Easy to check, too.

if(formatDate( input ) === "") {

}

The error could seem too unforgiving and too burdensome to the
developer. It is somewhat a matter of taste. I do tend to not favor
special return codes. Then again, Exception handling in javascript could
be a little better.


Consider a Table in which there is a column
of dates some of which are, for other reasons, not present. An empty
string does not look like a string, when written.

What "writing" does the function perform?

None, right? OK then. No alerts. No writing. No forms.

Decouple what you see in your test page with the role of this function.
That role is to format a date to a string value. That's it.
The ISO 8601 Extended format can be understood internationally, without
xxx ^An (there are more than one) (don't use Any[0])
world-wide ---> xxxxxxxxxxxxxx
ISO 8601 Extended formats can be...
No; that definitely implies that all of them can be.

or

[Most|Common|Many] 8601 Extended formats can be...

or even

Many common ISO 8601 Extended formats can be..
Obvious minor variations such as year outside 0000-9999 and the
presence
of time fields apart, there are not enough extended formats to justify
"Many".
So going with "Common ISO 8601 Extended formats..."

To be convincing, you will need to explain here which common ones fit
the rest of what you say. In the FAQ context, one needs something
stronger than "in each country, there will be some who understand".

That would certainly help.
Take today's date in the various ISO extended formats to different young
shop assistants, asking what's that? Probably, "YYYY-MM-DD" will be
recognised as a funny way of writing the date; the others may well be
considered as some strange sort of part number.

I do not know which are "common" or how common they are, or what the
statistical understandability of each is.

There should be some sort of research done on the matter. It could be as
simple as showing flashcards and asking the subject to read the date in
the natural language.

Researcher: [shows card "2002-11-12"]
Subject (American): "November 12, two thousand and two".

Researcher: [shows card "1952-02-12T10:27:29"]
Subject (British): Arse!

All kidding aside, my point is that I don't actually know which are
understandable and by whom. I believe that YYYY-MM-DD is easy to
understand because 1) I have noticed others find it intuitive, and 2)
the w3c uses it as a QA tip.

I have noticed that when the form has ____/__/__. I can cross those
blanks out, and write a recent date above in the format YYYY-MM-DD. They
also had no problem consuming my birth date. Not even a question about
it. Mind you, these are non-technical jobs held by Americans who
probably seldom see that format.
Yes. I wrote what I meant to write; there's a read error. There's no
semantic difference in this context in English between "fix" and
"script".

You can ask me to use "postscript," but I doubt that would go over well.

[...]
You need to learn to write English so that it can be unambiguously
parsed by others. That can be read as either of
Allowing (leading/trailing space only) keeps it simpler.
Allowing leading/trailing space (only keeps it simpler).

The regexp allows only leading/trailing space. This keeps the function
simpler.

That's right. But, at the ends of YYYY-MM-DD, it should be \D* . One
wants to reject a digit in that end position; there is no need to reject
anything else.

OK.


Str. It is expected to be a string; it is only hoped that it will
represent a good date.

Str does not sound like an apt or descriptive name to me. It seems far
too general. The convention for UpperCamelCase is to reserve it for
constructors. Thus, "Str" would seem to be some sort of constructor and
would not indicate anything about dates.
Call it YYYY_MM_DD.

YYYY_MM_DD does not indicate what the function does.

formatYYYY_MM_DD ?

var date = new Date(NaN),
isoExp, parts;
isoExp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/;
No general need to check field lengths, except for not exceeding DD.
The pattern is YYYY-MM-DD, and that is what the regexp checks (and
allows whitespace on the ends).

One needs to consider whether the code should check that the string is a
correct production of the ISO rules or should check that a valid date is
represented more-or-less in the ISO manner. For typed input, there's no
need to enforce rigour in the separators; "YYYY-MM-DD" is ISO but it's
easier to type "YYYY MM DD".

In fact the RegExp should be considered as an argument to the process of
typing the function.

function parseISO8601( dateStringInRange ) {
var date = new Date(NaN),
isoExp, parts;
isoExp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/;
parts = isoExp.exec(dateStringInRange);

if(parts) {
^
That looks like a call of the function 'if'. Goodman uses a space.
Flanagan uses a space.

I disagree that it looks like a function call of "if".
date.setFullYear(parts[1], parts[2] - 1, parts[3]);
if( parts[1] != date.getMonth() + 1 ) {
date.setTime(NaN);
} else {
date.setHours(0, 0, 0, 0);
}
}
return date;
}

There's little point in reviewing untested code, as that obviously is.

document.write("all should be true: \n",[
'isNaN(parseISO8601("0000-01-00")) '
+isNaN(parseISO8601("0000-01-00")),

'isFinite(parseISO8601("0000-01-01")) '
+isFinite(parseISO8601("0000-01-01")),

'isNaN(parseISO8601("0000-00-01")) '
+isNaN(parseISO8601("0000-00-01")),

// 2000 was a leap year.
'isFinite(parseISO8601("2000-02-29")) '
+isFinite(parseISO8601("2000-02-29")),

'isNaN(parseISO8601("000-01-01")) '
+isNaN(parseISO8601("000-01-01")),

'isFinite(parseISO8601("9999-12-31")) '
+isFinite(parseISO8601("9999-12-31")),

'isNaN(parseISO8601("9999-12-32")) '
+isNaN(parseISO8601("9999-12-32"))
].join("\n"));


Result FF, Safari, IE, Opera, Chrome:

all should be true:
isNaN(parseISO8601("0000-01-00")) true
isFinite(parseISO8601("0000-01-01")) true
isNaN(parseISO8601("0000-00-01")) true
isFinite(parseISO8601("2000-02-29")) true
isNaN(parseISO8601("000-01-01")) true
isFinite(parseISO8601("9999-12-31")) true
isNaN(parseISO8601("9999-12-32")) true

According to what you wrote on your site, you did not test on the
Motorola browser that you warn about. If you have a different result, or
a different test, please post up.

What did you have in mind?

Going out now. Yes, I do go out sometimes for purposes other than exercise.

Garrett
 
G

Garrett Smith

Dr said:
In comp.lang.javascript message <[email protected]
september.org>, Sat, 13 Jun 2009 09:58:24, Garrett Smith


And they clearly state that ISO 8601 first came out in 1988, which is
before JavaScript. 2004 is the 3rd edition. They also imply that
earlier ISO standards favoured Y M D order. Real Americans disdain
standards, especially non-American ones.


There are only two ISO 8601 formats for Gregorian dates in AD 0000-9999;
YYYYMMDD and YYYY-MM-DD. Browsers handle YYYY/MM/DD, and it's easy to
convert those to that (not necessarily optimal, of course).
There may be only two Complete representations for a calendar date,
there is still room to have representations with reduced accuracy.

YY Century
YYYY Specific Year
YYYY-MM Specific Month
YYYY-MM-DD Complete Representation

There are also expanded representations:-
±YYYYY Century
±YYYYY-MM Specific Month
±YYYYY-MM-DD Complete Representation


There are also representations with weeks:-

|
| Basic format: YYYYWwwD Example: 1985W155
| Extended format: YYYY-Www-D Example: 1985-W15-5
|
| 4.1.4.3 Representations with reduced accuracy
|...
In an extremely limited manner. They are really only addressing the
JSON formats. And it's not entirely too late to hope that the "Final
Draft" will be followed by a better one.

As you may have seen, toISOString seems to be going to change to throw
when called on an "invalid date" (value NaN).

You are welcome to drop a quick note on that thread.
All of the formats that fully specify a date are useful. And it's not
too difficult to code for them all in JavaScript; therefore it could be
easily enough done in whatever the JavaScript engine is written in - as
long as no-one copies MS DatePart. However, YYYY-MM-DD will be
commonest; start there.

Yes. Date.parse must handle that the draft only specifies one format:-

| The Simplified ISO 8601 format is as follows:
| YYYY-MM-DDTHH:mm:ss.sssTZ

It is not hard to parse out a result from the format currently specified
as the return value of ES5's Date.prototype.toISOString.
Why 1582? Proleptic Gregorian is often enough wanted, and few places
changed calendar in 1582. You'll be wanting the Swedish Calendar next;
and, for the Russian marker, Orthodox Easter.

What makes you think that?

Michael J. Ryan commented:

| What I don't get is why "2009-01-20" (iso-style formatting) is an
| invalid new Date()...

Somehow you mistook my response to be some sort of proposal. Now you
suggest that I would next be wanting Swedish Calendar, etc.

Implementations have not implemented their own extensions to the
language and a possible explanation is the number of allowed formates in
ISO 8601. It's my own conjecture of possible reasons to try and explain
Michael's observation.

The year 1582 is significant in calendar history. It is mentioned in ISO
8601:2004, section 3.2.1 and in the HTML 5 Working Draft's <time>
element[1].

| For dates before the introduction of the Gregorian calendar, authors
| are encouraged to not use the time element, or else to be very careful
| about converting dates and times from the period to the Gregorian
| calendar. This is complicated by the manner in which the Gregorian
| calendar was phased in, which occurred at different times in different
| countries, ranging from partway through the 16th century all the way
| to early in the 20th.

HTML 5 is a working draft. As such, it is subject to change.
The ECMAScript 5 recognizes only with one format which is intended
primarily for use with JSON. The TG 39 committee does not consider
human consumption for ISO 8601 and Allen has even gone as far as to
state that ISO 8601 is not intended for human consumption[2].

That's his view. It is not supported by ISO 8601, which is for
information interchange and does not reject human participation. Some
formats are more suitable for human use, others more for machine use. I
use both YYYY-MM-DD and YYYYMMDD when writing with pen and ink,
depending on who is expected to read it.

The Extended format YYYY-MM-DD seems easier.
The reasons why YYYY-MM-DD is best for machine use are equally valid for
human use; it's better than DD/MM/YYYY or the absurd MM/DD/YYYY.

It avoids ambiguity. I've added a link to the w3c QA tip. I know, you
didn't want it there. I know the page is not comprehensive. The reasons
for adding are that it is 1) an official w3c document that 2) explains
the problem with ambiguous formats 3) in a way that is easy for the
reader to digest.

If there are complaints, that link can be removed. Ideally, though,
constructive comments could be sent to the author of that page who could
then update it.

Garrett

[1]http://www.whatwg.org/specs/web-apps/current-work/#the-time-element
 
E

Evertjan.

Dr J R Stockton wrote on 13 jun 2009 in comp.lang.javascript:
One cannot expect Americans to consider international standards, [...]

But they're not all bad - remember J Jerome.

according to other standards remember it would be Jerome J.
 
T

Thomas 'PointedEars' Lahn

Dr said:
Garrett Smith posted:

Yes. I wrote what I meant to write; there's a read error. There's no
semantic difference in this context in English between "fix" and
"script".

Yes, there is. `suffix' currently means "attached after", _not_ "attached
below". A subscript ("written below") might be called "subfix" ("attached
below"), but certainly _not_ "suffix". You cannot use only parts of the
etymology of a word in the attempt to define its proper meaning in current
language.

<http://en.wiktionary.org/wiki/suffix>
<http://dictionary.cambridge.org/define.asp?key=79648&dict=CALD>

(Oxford Online Dictionary¹ is down ATM, but I'm sure you will find plenty of
other dictionaries proving you wrong.)


PointedEars
___________
¹ <http://www.askoxford.com/dictionaries/?view=uk>
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Sat, 13 Jun 2009 17:35:46, Garrett Smith
Easy to check, too.

if(formatDate( input ) === "") {

}

Any known sort of non-date result is easy enough to check - if the
developer thinks of it.

Consider a Table in which there is a column

What "writing" does the function perform?

None, right? OK then. No alerts. No writing. No forms.

Decouple what you see in your test page with the role of this function.
That role is to format a date to a string value. That's it.


The intent should be for it to be a good routine, not liable to give
undetected error in actual use. The most probable reason for creating a
date string is to write it to a medium outside the program - the screen,
a file, a comms link, for example.

To encourage testing the result, one can make the function return a
(non-Date) object. For input, I have one in which such an object has
two properties. The first is 3 for a pattern error, 1 for a YMD error,
and false for a good date, in which case the second property is a Date
Object. One is then encouraged to write something like
if (result.Bad) <handleError>
<use> result.D


That would certainly help.


I do not know which are "common" or how common they are, or what the
statistical understandability of each is.
Researcher: [shows card "2002-11-12"]
Subject (American): "November 12, two thousand and two".

Researcher: [shows card "1952-02-12T10:27:29"]
Subject (British): Arse!

That is not a date; not today's, not even that of HM's first Tuesday as
such. It has a separator not expected to be presented to people; and it
has a time; and we would not use that word ("Ass" implies "fool", and
the vulgar prefer more potent words. Granted, that's why Malvern hosted
an RSRE).
All kidding aside, my point is that I don't actually know which are
understandable and by whom.

You should be an editor. You are not called on to write about what you
do not know.

You can ask me to use "postscript," but I doubt that would go over well.

In English, Postscript uses Post to mean "after in time". It also has
another meaning in computing.



Well, (\D|$)




I disagree that it looks like a function call of "if".

I searched 67 days of this newsgroup, omitting spam. There are 121
"if(" and 387 "if (". The FAQ contains 8 of the former (several written
by you) and two of the latter, so the difference in non-FAQ use will be
greater.



date.setFullYear(parts[1], parts[2] - 1, parts[3]);
if( parts[1] != date.getMonth() + 1 ) {
There's little point in reviewing untested code, as that obviously
is.

document.write("all should be true: \n",[
'isNaN(parseISO8601("0000-01-00")) '
+isNaN(parseISO8601("0000-01-00")),
...

Different code. It is clearly wrong to compare parts[1] with the month.

Code for the FAQ **must** be copy'n'pasted from working tested code.
Hand-copying or adjusting is unreliable.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]>, Sun, 14
Jun 2009 14:09:11 said:
Yes, there is. `suffix' currently means "attached after", _not_ "attached
below". A subscript ("written below") might be called "subfix" ("attached
below"), but certainly _not_ "suffix". You cannot use only parts of the
etymology of a word in the attempt to define its proper meaning in current
language.

You are a fool to think that the English language is exactly what you
read in books or even hear from teachers.

And you should give up your juvenile habit of responding to as many
articles as you can, as quickly as possible, regardless of whether any
useful purpose is served.

It is noticeable, indeed, that you are becoming increasingly careless in
what you have, often needing to correct yourself.

Such practices only combine with your intrinsic nastyness.

KETFOB.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]
september.org>, Sat, 13 Jun 2009 23:50:27, Garrett Smith
There may be only two Complete representations for a calendar date,
there is still room to have representations with reduced accuracy.

The topic is the representations of dates; not of partial dates.
Reduced representations of date are irrelevant.

There are also representations with weeks:-

Those are not Gregorian dates, though they are based on the Gregorian
Calendar. Likewise Ordinal Dates.


What makes you think that?

Obvious extension of wanting >1582. Generality should not be wantonly
removed; restrictions can be added by those who need them.

Also, why > 1582? About 30% of dates in 1582 Rome were Gregorian.
=

More seriously, JavaScript has long used the proleptic astronomical
Gregorian calendar (the proleptic Gregorian calendar for strings).


Implementations have not implemented their own extensions to the
language and a possible explanation is the number of allowed formates
in ISO 8601. It's my own conjecture of possible reasons to try and
explain Michael's observation.

American disregard of "international" interests is a sufficient and
likely explanation. But it could just be ignorance.


This is complicated by the manner in which the Gregorian
| calendar was phased in, which occurred at different times in different
| countries, ranging from partway through the 16th century all the way
| to early in the 20th.


JavaScript, as supplied, does not support pre-Gregorian dates & times as
then written; that can sufficiently easily be done, if needed, in
script. <js-date8.htm> refers.


The ECMAScript 5 recognizes only with one format which is intended
primarily for use with JSON. The TG 39 committee does not consider
human consumption for ISO 8601 and Allen has even gone as far as to
state that ISO 8601 is not intended for human consumption[2].
That's his view. It is not supported by ISO 8601, which is for
information interchange and does not reject human participation. Some
formats are more suitable for human use, others more for machine use. I
use both YYYY-MM-DD and YYYYMMDD when writing with pen and ink,
depending on who is expected to read it.

The Extended format YYYY-MM-DD seems easier.

That is for me to decide, when I am writing. I use the extended form
except where brevity is necessary and will be understood. Sometimes I
use Extended format and a fine-point "Digital" pen instead.

It avoids ambiguity. I've added a link to the w3c QA tip. I know, you
didn't want it there. I know the page is not comprehensive. The reasons
for adding are that it is 1) an official w3c document that 2) explains
the problem with ambiguous formats 3) in a way that is easy for the
reader to digest.

Better to cite Markus Kuhn (in Wikipedia). He does not have W3's formal
authority, but he (and his address) command greater respect. See his
Ref. 7.



* An unreasonably large Web page (4 MB?) - according to
<http://thegospelvision.blogspot.com/2009/03/bible-statistics.html>,
there are more bytes in that than there are letters in the Bible.
* They appear to be working to ISO 8601:2000, alas. But they seem not
to mention 8601. That is bad.
* "Time zones differ based on daylight savings time." That is wrong.
* No mention of the year starting in March, AFAICS.
* "8592-01-01T02:09+02:09" - Unlikely IMHO that in 8592 an offset of 2h
9m will be used. For strange offsets, Dublin (or Amsterdam) time could
be used.
* They seem to have omitted yyyy-Www-d and Ordinal Dates.
 
D

Dr J R Stockton

In comp.lang.javascript message <[email protected]>
Dr J R Stockton wrote on 13 jun 2009 in comp.lang.javascript:
One cannot expect Americans to consider international standards, [...]

But they're not all bad - remember J Jerome.

according to other standards remember it would be Jerome J.

Are you sure that you are thinking of the correct J Jerome?
 
T

Thomas 'PointedEars' Lahn

Dr said:
Thomas 'PointedEars' Lahn posted:

You are a fool to think that the English language is exactly what you
read in books or even hear from teachers.

You are a fool to think that you are a considerable authority regarding the
English language.


PointedEars
 
M

Michael J. Ryan

In comp.lang.javascript message <[email protected]
september.org>, Fri, 12 Jun 2009 23:25:04, Michael J. Ryan


With "/" "/".


One cannot expect Americans to consider international standards,
especially ones only seven years old. ISO 8601 appeared in 1988,
JavaScript in the USA in 1995. They did not even provide for DD/MM/YYYY
& DD.MM.YYYY, used in so many countries.

Understandable... it just irks me that almost every rdbms I've ever used
accepts YYYY-MM-DD, and js doesn't
Remember : in implementing getYear(), they failed to consider
sufficiently that the 1900's had only half a decade to run, even though
corresponding events had occurred twice before in their country.

Another irksome point.. though a standard for
Date.prototype.toFormat(formatstring) and a Date.fromFormat(format, input)
would be nice... maybe overloading toString and adding fromString, but that
seems to bely convention.
 

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,098
Messages
2,570,625
Members
47,236
Latest member
EverestNero

Latest Threads

Top