dd/mm/yyyy Date Compare Problem

A

Assimalyst

Hi,

I have a working script that converts a dd/mm/yyyy text box date entry
to yyyy/mm/dd and compares it to the current date, giving an error
through an asp.net custom validator, it is as follows:

function doDateCheckNow(source, args)
{
var oDate = document.getElementById(source.controltovalidate); //
dd/mm/yyyy
var arrDate = oDate.value.split("/");
var useDate = new Date(arrDate[2], arrDate[1]-1, arrDate[0]); //
yyyy/mm/dd
var today = new Date();

if (useDate <= today)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

I have then attempted to use an adapted version of this to compare a
date entered into a text box (dodTxtBx) with the text loaded into an
asp.net label (dobLbl):

function doDateCheckDod(dodTxtBx, dobLbl, args)
{
// Convert DOD to javascript date format
var oDodDate = dodTxtBx; // dd/mm/yyyy
var arrDodDate = oDodDate.value.split("/");
var useDodDate = new Date(arrDodDate[2], arrDodDate[1],
arrDodDate[0]); // yyyy/mm/dd

// Convert DOB to javascript date format
var oDobDate = dobLbl; // dd/mm/yyyy
var arrDobDate = oDobDate.value.split("/");
var useDobDate = new Date(arrDobDate[2], arrDobDate[1],
arrDobDate[0]); // yyyy/mm/dd

if (useDobDate < useDodDate)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

But this creates errors on the page when it runs and always fails the
custom validator.

Any ideas why?

Many Thanks
 
J

jshanman

Assimalyst said:
Hi,

I have a working script that converts a dd/mm/yyyy text box date entry
to yyyy/mm/dd and compares it to the current date, giving an error
through an asp.net custom validator, it is as follows:

function doDateCheckNow(source, args)
{
var oDate = document.getElementById(source.controltovalidate); //
dd/mm/yyyy
var arrDate = oDate.value.split("/");
var useDate = new Date(arrDate[2], arrDate[1]-1, arrDate[0]); //
yyyy/mm/dd
var today = new Date();

if (useDate <= today)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

I have then attempted to use an adapted version of this to compare a
date entered into a text box (dodTxtBx) with the text loaded into an
asp.net label (dobLbl):

function doDateCheckDod(dodTxtBx, dobLbl, args)
{
// Convert DOD to javascript date format
var oDodDate = dodTxtBx; // dd/mm/yyyy
var arrDodDate = oDodDate.value.split("/");
var useDodDate = new Date(arrDodDate[2], arrDodDate[1],
arrDodDate[0]); // yyyy/mm/dd

// Convert DOB to javascript date format
var oDobDate = dobLbl; // dd/mm/yyyy
var arrDobDate = oDobDate.value.split("/");
var useDobDate = new Date(arrDobDate[2], arrDobDate[1],
arrDobDate[0]); // yyyy/mm/dd

if (useDobDate < useDodDate)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

But this creates errors on the page when it runs and always fails the
custom validator.

Any ideas why?

Many Thanks

Your function works fine for me when called correctly: (IE6 & Firefox
1.5)

<input type="text" id="timetest" onblur="doDateCheckNow(this);">

function doDateCheckNow(source) {
var oDate = source; //dd/mm/yyyy
var arrDate = oDate.value.split("/");
var useDate = new Date(arrDate[2], arrDate[1]-1, arrDate[0]);
//yyyy/mm/dd
var today = new Date();

if (useDate <= today)
{
alert("true");
}
else
{
alert("false");
}

}

How are you calling your function? Try putting some alerts after each
variable is set/changes, to make sure your getting the text data from
your fields.

I don't know that this has anything to do with ASP...

- JS
 
S

Steve Kostecke

jshanman said:
Assimalyst said:
Hi,

I have a working script that converts a dd/mm/yyyy text box date
entry to yyyy/mm/dd and compares it to the current date, giving an
error through an asp.net custom validator, it is as follows:

function doDateCheckNow(source, args)
{
var oDate = document.getElementById(source.controltovalidate); //
dd/mm/yyyy
var arrDate = oDate.value.split("/");
var useDate = new Date(arrDate[2], arrDate[1]-1, arrDate[0]); //
yyyy/mm/dd
var today = new Date();

if (useDate <= today)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

I have then attempted to use an adapted version of this to compare a
date entered into a text box (dodTxtBx) with the text loaded into an
asp.net label (dobLbl):

function doDateCheckDod(dodTxtBx, dobLbl, args)
{
// Convert DOD to javascript date format
var oDodDate = dodTxtBx; // dd/mm/yyyy
var arrDodDate = oDodDate.value.split("/");
var useDodDate = new Date(arrDodDate[2], arrDodDate[1],
arrDodDate[0]); // yyyy/mm/dd

// Convert DOB to javascript date format
var oDobDate = dobLbl; // dd/mm/yyyy
var arrDobDate = oDobDate.value.split("/");
var useDobDate = new Date(arrDobDate[2], arrDobDate[1],
arrDobDate[0]); // yyyy/mm/dd

if (useDobDate < useDodDate)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

But this creates errors on the page when it runs and always fails the
custom validator.

Any ideas why?

Many Thanks

Your function works fine for me when called correctly: (IE6 & Firefox
1.5)

Why doesn't it work in NN 4 ?
 
J

jshanman

Steve said:
jshanman said:
Assimalyst said:
Hi,

I have a working script that converts a dd/mm/yyyy text box date
entry to yyyy/mm/dd and compares it to the current date, giving an
error through an asp.net custom validator, it is as follows:

function doDateCheckNow(source, args)
{
var oDate = document.getElementById(source.controltovalidate); //
dd/mm/yyyy
var arrDate = oDate.value.split("/");
var useDate = new Date(arrDate[2], arrDate[1]-1, arrDate[0]); //
yyyy/mm/dd
var today = new Date();

if (useDate <= today)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

I have then attempted to use an adapted version of this to compare a
date entered into a text box (dodTxtBx) with the text loaded into an
asp.net label (dobLbl):

function doDateCheckDod(dodTxtBx, dobLbl, args)
{
// Convert DOD to javascript date format
var oDodDate = dodTxtBx; // dd/mm/yyyy
var arrDodDate = oDodDate.value.split("/");
var useDodDate = new Date(arrDodDate[2], arrDodDate[1],
arrDodDate[0]); // yyyy/mm/dd

// Convert DOB to javascript date format
var oDobDate = dobLbl; // dd/mm/yyyy
var arrDobDate = oDobDate.value.split("/");
var useDobDate = new Date(arrDobDate[2], arrDobDate[1],
arrDobDate[0]); // yyyy/mm/dd

if (useDobDate < useDodDate)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

But this creates errors on the page when it runs and always fails the
custom validator.

Any ideas why?

Many Thanks

Your function works fine for me when called correctly: (IE6 & Firefox
1.5)

Why doesn't it work in NN 4 ?

Matt Kruse is right, the proper way would actually be using the
..valueOf() (or getTime() method of the date object. This returns the
number of milliseconds from the Unix Epoch (Jan 1st 1970)

Therefore, if a date is more recent, the number of milliseconds would
be high whereas if the date is before the test date, then the number of
millieseconds would be less.

Re-written:
<input type="text" id="timetest" onblur="doDateCheckNow(this);">

function doDateCheckNow(source) {
var oDate = source; //dd/mm/yyyy
var arrDate = oDate.value.split("/");
var useDate = new Date(arrDate[2], arrDate[1]-1, arrDate[0]);
//yyyy/mm/dd
var today = new Date();

if (useDate.valueOf() < today.valueOf())
{
alert(useDate+" was before "+today);
}
else
{
alert(useDate+" will be after "+today);
}

}

- JS
 
T

Thomas 'PointedEars' Lahn

jshanman said:
Steve said:
jshanman said:
Assimalyst wrote:
[...]
var useDodDate = new Date(arrDodDate[2], arrDodDate[1],
arrDodDate[0]); // yyyy/mm/dd
[...]
var useDobDate = new Date(arrDobDate[2], arrDobDate[1],
arrDobDate[0]); // yyyy/mm/dd

if (useDobDate < useDodDate)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}
}

But this creates errors on the page when it runs and always fails the
custom validator.
[...]
Your function works fine for me when called correctly: (IE6 & Firefox
1.5)
Why doesn't it work in NN 4 ?

Matt Kruse is right, the proper way would actually be using the
.valueOf() (or getTime() method of the date object.

No, against it would not be any more or less proper than without
calling .valueOf() or .getTime(). Automatic type conversion does the job,
see ECMAScript 3 Edition 3 Final, section 11.8 (one wonders how many times
Matt must be told this). And it works perfectly fine in Mozilla/4.8 [en]
(X11; U; Linux 2.6.15.6-20060314.201202+0100 i686).

However,

args.isValid = (useDobDate < useDodDate);

is more efficient.


PointedEars
 
T

Thomas 'PointedEars' Lahn

Thomas said:
No, against it would not be any more or less proper than without
calling .valueOf() or .getTime(). Automatic type conversion does the job,
see ECMAScript 3 Edition 3 Final, section 11.8 (one wonders how many times
Matt must be told this). And it works perfectly fine in Mozilla/4.8 [en]
(X11; U; Linux 2.6.15.6-20060314.201202+0100 i686). [...]

That also works in

Mozilla/4.74 [en] (X11; U; Linux 2.6.15.6-20060314.201202+0100 i686; Nav)

down to

Mozilla/4.08 [en] (WinNT; U ;Nav)


PointedEars
 
D

Dr John Stockton

JRS: In article <[email protected]>
, dated Fri, 28 Apr 2006 06:38:24 remote, seen in
news:comp.lang.javascript said:
I have a working script that converts a dd/mm/yyyy text box date entry
to yyyy/mm/dd

AFAICS, you do not. It converts "dd/mm/yyyy" to a Date Object, but
yyyy/mm/dd is not involved.
and compares it to the current date, giving an error
through an asp.net custom validator, it is as follows:

function doDateCheckNow(source, args)
{
var oDate = document.getElementById(source.controltovalidate); //
dd/mm/yyyy

Don't let your posting agent line-wrap; posted code should be directly
executable.
var arrDate = oDate.value.split("/");
var useDate = new Date(arrDate[2], arrDate[1]-1, arrDate[0]); //
yyyy/mm/dd

or
var useDate = // via yyyy/mm/dd
new Date(oDate.value.replace(/(..).(..).(....)/, "$3/$2/$1"))
var today = new Date();
if (useDate <= today)
{
args.IsValid = true;
}
else
{
args.IsValid = false;
}

Should be args.IsValid = useDate <= today
}

function doDateCheckDod(dodTxtBx, dobLbl, args)
{
// Convert DOD to javascript date format
var oDodDate = dodTxtBx; // dd/mm/yyyy
var arrDodDate = oDodDate.value.split("/");
var useDodDate = new Date(arrDodDate[2], arrDodDate[1],
arrDodDate[0]); // yyyy/mm/dd

// Convert DOB to javascript date format
var oDobDate = dobLbl; // dd/mm/yyyy
var arrDobDate = oDobDate.value.split("/");
var useDobDate = new Date(arrDobDate[2], arrDobDate[1],
arrDobDate[0]); // yyyy/mm/dd

Repeated code should generally be put in a function. When that is done,
and the function is small, temporary local variables do not need long
names.
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Fri, 28 Apr 2006
09:04:26 remote, seen in Matt Kruse
You can't compare dates this way. Instead, you should probably compare their
.getTime() values.

I can; why should he be unable to?

In principle, .valueOf() gets the internal value, and .getTime() gets
whatever it wants, which happens to be the same. IIRC, in a context
wanting a Number, .valueOf() is used by default. Comparison is such a
context. ECMA 11.8.5, steps 1 & 2.

But, to make the conversion both brief and explicit,
if (+useDate <= +today)
since unary + converts to Number.
For parsing dates, converting between formats, and comparing, see my Date
library at http://www.JavascriptToolbox.com/lib/date/ which might make your
life easier.

I'd not use a library from someone who does not know that a relational
operator likes to compare Numbers. It might be bloated.


I've not looked at your library code recently (as you may recall, I use
News off-line), so don't know the style.

But ISTM that if you were to write in a subset of javascript,
specifically such that // (and maybe /* */) only occurred as real
comment markers and not in strings, regexps, etc., then it might be
quite easy to produce, in javascript, a de-commenter and de-indenter.
Your library could be fetched in its full glory, but readily reduced to
the working parts without positive obfuscation.

It could operate like the paragraph-pack in js-quick.htm; copy into
textarea, press button, copy out.

But perhaps you already have something better.
 
M

Matt Kruse

Dr said:
I can; why should he be unable to?

I was under the (probably mistaken) impression that the explicit conversion
failed in some browser versions for dates, and therefore wasn't good to use.
As this belief goes back a few years, I don't even remember where it
originated.
I've not looked at your library code recently (as you may recall, I
use News off-line), so don't know the style.

I've re-written my date code recently to extend Date using prototypes for
most functions. One thing you might not like is that I don't use regular
expressions to parse text. Instead, I still use the manual substring
approach. Someday I'll update it further, but it's solid as-is, and I don't
have a lot of time, so updating working code doesn't seem like the best use
of it :)
it might be
quite easy to produce, in javascript, a de-commenter and de-indenter.
Your library could be fetched in its full glory, but readily reduced
to the working parts without positive obfuscation.
...But perhaps you already have something better.

I do this in real-time in PHP, actually. I write my code with full comments
and in a style that can be easily reduced. It is then fetched via a PHP
script which either delivers the full code or compacted code. Also, if the
library has any dependencies it can detect this, prepend them into the
source, and deliver a "combined" version. In all my pages and test cases, I
link to the compacted version of the code to make sure that no bugs are
introduced during the compacting.

I also have a fairly extensive set of over 150 test cases at
http://www.javascripttoolbox.com/lib/date/test.php which runs the javascript
in the browser and makes assertions similar to XUnit test suites. It works
well for cross-browser testing of libs like this.

Since you read offline, I'll paste my source below in case you want to look
at it. I'm always open to suggestions, although I can probably already name
many of the same ones that you might offer ;) Hope the code isn't too long,
and of course beware of wrapping.

/*
Date functions

These functions are used to parse, format, and manipulate Date objects.
See documentation and examples at http://www.JavascriptToolbox.com/lib/date/

*/
Date.$VERSION = 1.01;

// Utility function to append a 0 to single-digit numbers
Date.LZ = function(x) {return(x<0||x>9?"":"0")+x};
// Full month names. Change this for local month names
Date.monthNames = new
Array('January','February','March','April','May','June','July','August','September','October','November','December');
// Month abbreviations. Change this for local month names
Date.monthAbbreviations = new
Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
// Full day names. Change this for local month names
Date.dayNames = new
Array('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
// Day abbreviations. Change this for local month names
Date.dayAbbreviations = new
Array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
// Used for parsing ambiguous dates like 1/2/2000 - default to preferring
'American' format meaning Jan 2.
// Set to false to prefer 'European' format meaning Feb 1
Date.preferAmericanFormat = true;

// If the getFullYear() method is not defined, create it
if (!Date.prototype.getFullYear) {
Date.prototype.getFullYear = function() { var yy=this.getYear(); return
(yy<1900?yy+1900:yy); }
}

// Parse a string and convert it to a Date object.
// If no format is passed, try a list of common formats.
// If string cannot be parsed, return null.
// Avoids regular expressions to be more portable.
Date.parseString = function(val, format) {
// If no format is specified, try a few common formats
if (typeof(format)=="undefined" || format==null || format=="") {
var generalFormats=new Array('y-M-d','MMM d, y','MMM
d,y','y-MMM-d','d-MMM-y','MMM d','MMM-d','d-MMM');
var monthFirst=new Array('M/d/y','M-d-y','M.d.y','M/d','M-d');
var dateFirst =new Array('d/M/y','d-M-y','d.M.y','d/M','d-M');
var checkList=new
Array(generalFormats,Date.preferAmericanFormat?monthFirst:dateFirst,Date.preferAmericanFormat?dateFirst:monthFirst);
for (var i=0; i<checkList.length; i++) {
var l=checkList;
for (var j=0; j<l.length; j++) {
var d=Date.parseString(val,l[j]);
if (d!=null) {
return d;
}
}
}
return null;
}

this.isInteger = function(val) {
for (var i=0; i < val.length; i++) {
if ("1234567890".indexOf(val.charAt(i))==-1) {
return false;
}
}
return true;
};
this.getInt = function(str,i,minlength,maxlength) {
for (var x=maxlength; x>=minlength; x--) {
var token=str.substring(i,i+x);
if (token.length < minlength) {
return null;
}
if (this.isInteger(token)) {
return token;
}
}
return null;
};
val=val+"";
format=format+"";
var i_val=0;
var i_format=0;
var c="";
var token="";
var token2="";
var x,y;
var year=new Date().getFullYear();
var month=1;
var date=1;
var hh=0;
var mm=0;
var ss=0;
var ampm="";
while (i_format < format.length) {
// Get next token from format string
c=format.charAt(i_format);
token="";
while ((format.charAt(i_format)==c) && (i_format < format.length)) {
token += format.charAt(i_format++);
}
// Extract contents of value based on format token
if (token=="yyyy" || token=="yy" || token=="y") {
if (token=="yyyy") {
x=4;y=4;
}
if (token=="yy") {
x=2;y=2;
}
if (token=="y") {
x=2;y=4;
}
year=this.getInt(val,i_val,x,y);
if (year==null) {
return null;
}
i_val += year.length;
if (year.length==2) {
if (year > 70) {
year=1900+(year-0);
}
else {
year=2000+(year-0);
}
}
}
else if (token=="MMM" || token=="NNN"){
month=0;
var names =
(token=="MMM"?(Date.monthNames.concat(Date.monthAbbreviations)):Date.monthAbbreviations);
for (var i=0; i<names.length; i++) {
var month_name=names;
if
(val.substring(i_val,i_val+month_name.length).toLowerCase()==month_name.toLowerCase())
{
month=(i%12)+1;
i_val += month_name.length;
break;
}
}
if ((month < 1)||(month>12)){
return null;
}
}
else if (token=="EE"||token=="E"){
var names = (token=="EE"?Date.dayNames:Date.dayAbbreviations);
for (var i=0; i<names.length; i++) {
var day_name=names;
if
(val.substring(i_val,i_val+day_name.length).toLowerCase()==day_name.toLowerCase())
{
i_val += day_name.length;
break;
}
}
}
else if (token=="MM"||token=="M") {
month=this.getInt(val,i_val,token.length,2);
if(month==null||(month<1)||(month>12)){
return null;
}
i_val+=month.length;
}
else if (token=="dd"||token=="d") {
date=this.getInt(val,i_val,token.length,2);
if(date==null||(date<1)||(date>31)){
return null;
}
i_val+=date.length;
}
else if (token=="hh"||token=="h") {
hh=this.getInt(val,i_val,token.length,2);
if(hh==null||(hh<1)||(hh>12)){
return null;
}
i_val+=hh.length;
}
else if (token=="HH"||token=="H") {
hh=this.getInt(val,i_val,token.length,2);
if(hh==null||(hh<0)||(hh>23)){
return null;
}
i_val+=hh.length;
}
else if (token=="KK"||token=="K") {
hh=this.getInt(val,i_val,token.length,2);
if(hh==null||(hh<0)||(hh>11)){
return null;
}
i_val+=hh.length;
hh++;
}
else if (token=="kk"||token=="k") {
hh=this.getInt(val,i_val,token.length,2);
if(hh==null||(hh<1)||(hh>24)){
return null;
}
i_val+=hh.length;
hh--;
}
else if (token=="mm"||token=="m") {
mm=this.getInt(val,i_val,token.length,2);
if(mm==null||(mm<0)||(mm>59)){
return null;
}
i_val+=mm.length;
}
else if (token=="ss"||token=="s") {
ss=this.getInt(val,i_val,token.length,2);
if(ss==null||(ss<0)||(ss>59)){
return null;
}
i_val+=ss.length;
}
else if (token=="a") {
if (val.substring(i_val,i_val+2).toLowerCase()=="am") {
ampm="AM";
}
else if (val.substring(i_val,i_val+2).toLowerCase()=="pm") {
ampm="PM";
}
else {
return null;
}
i_val+=2;
}
else {
if (val.substring(i_val,i_val+token.length)!=token) {
return null;
}
else {
i_val+=token.length;
}
}
}
// If there are any trailing characters left in the value, it doesn't
match
if (i_val != val.length) {
return null;
}
// Is date valid for month?
if (month==2) {
// Check for leap year
if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
if (date > 29){
return null;
}
}
else {
if (date > 28) {
return null;
}
}
}
if ((month==4)||(month==6)||(month==9)||(month==11)) {
if (date > 30) {
return null;
}
}
// Correct hours value
if (hh<12 && ampm=="PM") {
hh=hh-0+12;
}
else if (hh>11 && ampm=="AM") {
hh-=12;
}
return new Date(year,month-1,date,hh,mm,ss);
}

// Check if a date string is valid
Date.isValid = function(val,format) {
return (Date.parseString(val,format) != null);
}

// Check if a date object is before another date object
Date.prototype.isBefore = function(date2) {
if (date2==null) {
return false;
}
return (this.getTime()<date2.getTime());
}

// Check if a date object is after another date object
Date.prototype.isAfter = function(date2) {
if (date2==null) {
return false;
}
return (this.getTime()>date2.getTime());
}

// Check if two date objects have equal dates and times
Date.prototype.equals = function(date2) {
if (date2==null) {
return false;
}
return (this.getTime()==date2.getTime());
}

// Check if two date objects have equal dates, disregarding times
Date.prototype.equalsIgnoreTime = function(date2) {
if (date2==null) {
return false;
}
var d1 = new Date(this.getTime()).clearTime();
var d2 = new Date(date2.getTime()).clearTime();
return (d1.getTime()==d2.getTime());
}

// Format a date into a string using a given format string
Date.prototype.format = function(format) {
format=format+"";
var result="";
var i_format=0;
var c="";
var token="";
var y=this.getYear()+"";
var M=this.getMonth()+1;
var d=this.getDate();
var E=this.getDay();
var H=this.getHours();
var m=this.getMinutes();
var s=this.getSeconds();
var yyyy,yy,MMM,MM,dd,hh,h,mm,ss,ampm,HH,H,KK,K,kk,k;
// Convert real date parts into formatted versions
var value=new Object();
if (y.length < 4) {
y=""+(+y+1900);
}
value["y"]=""+y;
value["yyyy"]=y;
value["yy"]=y.substring(2,4);
value["M"]=M;
value["MM"]=Date.LZ(M);
value["MMM"]=Date.monthNames[M-1];
value["NNN"]=Date.monthAbbreviations[M-1];
value["d"]=d;
value["dd"]=Date.LZ(d);
value["E"]=Date.dayAbbreviations[E];
value["EE"]=Date.dayNames[E];
value["H"]=H;
value["HH"]=Date.LZ(H);
if (H==0){
value["h"]=12;
}
else if (H>12){
value["h"]=H-12;
}
else {
value["h"]=H;
}
value["hh"]=Date.LZ(value["h"]);
value["K"]=value["h"]-1;
value["k"]=value["H"]+1;
value["KK"]=Date.LZ(value["K"]);
value["kk"]=Date.LZ(value["k"]);
if (H > 11) {
value["a"]="PM";
}
else {
value["a"]="AM";
}
value["m"]=m;
value["mm"]=Date.LZ(m);
value["s"]=s;
value["ss"]=Date.LZ(s);
while (i_format < format.length) {
c=format.charAt(i_format);
token="";
while ((format.charAt(i_format)==c) && (i_format < format.length)) {
token += format.charAt(i_format++);
}
if (value[token] != null) {
result=result + value[token];
}
else {
result=result + token;
}
}
return result;
}

// Get the full name of the day for a date
Date.prototype.getDayName = function() {
return Date.dayNames[this.getDay()];
}

// Get the abbreviation of the day for a date
Date.prototype.getDayAbbreviation = function() {
return Date.dayAbbreviations[this.getDay()];
}

// Get the full name of the month for a date
Date.prototype.getMonthName = function() {
return Date.monthNames[this.getMonth()];
}

// Get the abbreviation of the month for a date
Date.prototype.getMonthAbbreviation = function() {
return Date.monthAbbreviations[this.getMonth()];
}

// Clear all time information in a date object
Date.prototype.clearTime = function() {
this.setHours(0);
this.setMinutes(0);
this.setSeconds(0);
this.setMilliseconds(0);
return this;
}

// Add an amount of time to a date. Negative numbers can be passed to
subtract time.
Date.prototype.add = function(interval, number) {
if (typeof(interval)=="undefined" || interval==null ||
typeof(number)=="undefined" || number==null) {
return this;
}
number = +number;
if (interval=='y') { // year
this.setFullYear(this.getFullYear()+number);
}
else if (interval=='M') { // Month
this.setMonth(this.getMonth()+number);
}
else if (interval=='d') { // Day
this.setDate(this.getDate()+number);
}
else if (interval=='w') { // Weekday
var step = (number>0)?1:-1;
while (number!=0) {
this.add('d',step);
while(this.getDay()==0 || this.getDay()==6) {
this.add('d',step);
}
number -= step;
}
}
else if (interval=='h') { // Hour
this.setHours(this.getHours() + number);
}
else if (interval=='m') { // Minute
this.setMinutes(this.getMinutes() + number);
}
else if (interval=='s') { // Second
this.setSeconds(this.getSeconds() + number);
}
return this;
}
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Fri, 28 Apr 2006
20:23:07 remote, seen in Matt Kruse
Dr John Stockton wrote:
I've re-written my date code recently to extend Date using prototypes for
most functions. One thing you might not like is that I don't use regular
expressions to parse text. Instead, I still use the manual substring
approach. Someday I'll update it further, but it's solid as-is, and I don't
have a lot of time, so updating working code doesn't seem like the best use
of it :)


I do this in real-time in PHP, actually.
...

I did mean that the de-*er would be distributed, for example on a web
page; then the material could be sent in full from library author to
each Web programmer, who could retail a full-glory reference copy but
use in pages the reduced version.
Since you read offline, I'll paste my source below in case you want to look
at it. I'm always open to suggestions, although I can probably already name
many of the same ones that you might offer ;) Hope the code isn't too long,
and of course beware of wrapping.

/*
Date functions

These functions are used to parse, format, and manipulate Date objects.
See documentation and examples at http://www.JavascriptToolbox.com/lib/date/

*/
Date.$VERSION = 1.01;

Quote pruned.
// Utility function to append a 0 to single-digit numbers
Date.LZ = function(x) {return(x<0||x>9?"":"0")+x};

x<0|| is probably not needed in this contest; but prudent.

Date.dayAbbreviations = new
Array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');

Add a Sunday at the end of the week, and you can match ISO 8601 too!

// If the getFullYear() method is not defined, create it
if (!Date.prototype.getFullYear) {
Date.prototype.getFullYear = function() { var yy=this.getYear(); return
(yy<1900?yy+1900:yy); }
}

I have heard that there is or has been a browser which, at least in
1900..2099, has getYear() returning Year%100, for which that fails. See
js-date0.htm, #gY, #gFY. OTOH, if your library is in use in conjunction
with such a browser, the problem will have been noticeable for six
years.

this.isInteger = function(val) {
for (var i=0; i < val.length; i++) {
if ("1234567890".indexOf(val.charAt(i))==-1) {
return false;
}
}
return true;
};

or this.isInteger = function(val) { return !/\D/.test(val) }
and name could be isNonNegInt. ISTM that both fail on empty strings;
unary + seems to accept an empty string as 0, but parseInt gives NaN.


// Is date valid for month?
if (month==2) {
// Check for leap year
if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
if (date > 29){
return null;
}
}
else {
if (date > 28) {
return null;
}
}
}

There's no need to evaluate Leapness unless it's Feb 29. Feb <29 is
always good; Feb >29 always bad.

I'd use Date Object readback, or an array [0,31,28,31,...,31] to look up
the maximum date for the month, then if date > maximum then if date = 29
then OK = Leap.


// Clear all time information in a date object
Date.prototype.clearTime = function() {
this.setHours(0);
this.setMinutes(0);
this.setSeconds(0);
this.setMilliseconds(0);
return this;
}

setTing can be combined in JS 1.3+

// Add an amount of time to a date. Negative numbers can be passed to
subtract time.

However, the amount of time actually added can depend on the date; Years
and Feb vary in length by a day, and days can vary by an hour.

Date.prototype.add = function(interval, number) {
else if (interval=='w') { // Weekday

I think you are adding a number of WORKING days, stepwise. You could do
div and mod 5, then add 7 times the div result and step the mod result.
It would be faster for long intervals.
var step = (number>0)?1:-1;
while (number!=0) {
this.add('d',step);
while(this.getDay()==0 || this.getDay()==6) {
this.add('d',step);
}
number -= step;
}
}


Adding Minutes, Seconds could be appreciably faster with setTime (but
then Minutes sometimes wrong for Lord Howe Island).


You have support for FIPS/ISO elsewhere?
 
M

Matt Kruse

Dr said:
I did mean that the de-*er would be distributed, for example on a web
page; then the material could be sent in full from library author to
each Web programmer, who could retail a full-glory reference copy but
use in pages the reduced version.

I don't see the difference - both the full version and the compacted version
are available on my site. A developer could download the full version for
reference and the compacted version for production. That's the intent, at
least :)
Add a Sunday at the end of the week, and you can match ISO 8601 too!

This array is only useful when getting the index from getDay(), so adding
another 'Sun' at the end would be pointless.
I have heard that there is or has been a browser which, at least in
1900..2099, has getYear() returning Year%100, for which that fails.

Which browser? That's a broken implementation of getYear() anyway, so anyone
using such a browser surely has other issues ;)
There's no need to evaluate Leapness unless it's Feb 29. Feb <29 is
always good; Feb >29 always bad.

Valid point.
However, the amount of time actually added can depend on the date;
Years and Feb vary in length by a day, and days can vary by an hour.

This is true, but the result should meet expectations. Some time units are
not absolute, like month and year. Yet adding a year to 1/1/X should always
result in 1/1/(x+1) regardless of how much time that period actually
contained.
I think you are adding a number of WORKING days, stepwise.

Weekday = Mon-Fri, no? "Working day" has the same meaning to most, but not
all. Perhaps the same is true of "weekday"?
You have support for FIPS/ISO elsewhere?

Depends on what you mean, exactly. The functions parse/format functions are
intended to be independent of any specific standard or locale.

Thanks for your feedback.
 
D

Dr John Stockton

JRS: In article <[email protected]>, dated Sun, 30 Apr 2006
09:26:12 remote, seen in Matt Kruse
Dr John Stockton wrote:

This array is only useful when getting the index from getDay(), so adding
another 'Sun' at the end would be pointless.

Since the code is extendible, it might have ISO functions added to it.

Which browser? That's a broken implementation of getYear() anyway, so anyone
using such a browser surely has other issues ;)

If I had thought to record which at the time (if it was stated) I would
now be able to tell you that. Actually, it's a sensible implementation
for a 2-digit year; no-one can want what getYear() gives without some
adjustment, but Year%100 can be used. The ECMA standard getYear is not
sensible, but doubtless was necessitated for compatibility. Function
getYear() should have provided Full Year, with a note on the effect of
%100.

This is true, but the result should meet expectations. Some time units are
not absolute, like month and year. Yet adding a year to 1/1/X should always
result in 1/1/(x+1) regardless of how much time that period actually
contained.

It should result in 0002/1/X ... . But ISTM that there must be possible
comment of adequate brevity :
// Increase/decrease a date component; negative numbers decrease.

To cover y & M, ISTM that there should be a note on what happens if the
nominal target date does not exist - a year ahead of 2004-02-29 or a
month ahead of 2006-03-31 for example - and possibly an option. If the
date changes, it should be set to either 1 or 0 as desired.

Weekday = Mon-Fri, no? "Working day" has the same meaning to most, but not
all. Perhaps the same is true of "weekday"?

Well, I had to look to be sure that it was not incrementing to the same
day of next week, i.e. by 7*number days. // Days, skips Sat/Sun

Depends on what you mean, exactly. The functions parse/format functions are
intended to be independent of any specific standard or locale.

But AIUI FIPS (Federal Information Processing Standard, for non-
Americans) calls for following ISO, which implies weeks Mon=1 .. Sun=7,
week numbering by reference to the First Thursday, etc.
 

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
473,770
Messages
2,569,584
Members
45,076
Latest member
OrderKetoBeez

Latest Threads

Top