reptile7's JavaScript blog
Sunday, January 14, 2007
Save the Date
Blog Entry #63

June 2016 Update:
(1) The demo in the legacy Script Tips #31-33 works just fine, so it is almost certainly not Joe but one of his successors at HTML Goodies who is to blame for the dysfunctional demo in the current Script Tips #31-33.
(2) Contra Netscape, the toLocaleDateString( ) method of the Date object does not go back to JavaScript 1.0 but was implemented in JavaScript 1.5 - it's not present in JavaScript 1.4 - so yes, we should cut Joe some slack for not using it.

As we did a couple of entries ago, let's go back to HTML Goodies' JavaScript Primers #3 and this time look at the date-formatting parts/effects of its scripts.
(1) The Primer #3 Script writes out: Today's date is 1-1-2007.
(2) Joe's Primer #3 Assignment answer writes out: You stopped by on: 1/1/2007.
"These date formats are so cold, so antiseptic," you are thinking to yourself. "It'd be way nicer if we could write out: Today is Monday January 1st, 2007." And you're in luck - Joe himself has crafted a script that creates and displays a text-based date in this very format, and he discusses it in HTML Goodies' JavaScript Script Tips #31, #32, and #33.

Joe posts the Script Tips #31-33 Script here but his demonstration thereof in Script Tips #31-33 does not work. Checking the Script Tips #31-33 source code shows that the script's [ and ] square bracket characters have been escaped with the [ and ] numeric character references, respectively, killing the script's effect. (91 and 93 are the respective ASCII code positions of the [ and ] characters.) Arrrgh!! Joe, you really should know better than this!

Anyway, the div below provides a 'real-date' demo of the Script Tips #31-33 Script followed by the script itself:

<script language="javascript">

DaysofWeek = new Array( );
DaysofWeek[0] = "Sunday";
DaysofWeek[1] = "Monday";
DaysofWeek[2] = "Tuesday";
DaysofWeek[3] = "Wednesday";
DaysofWeek[4] = "Thursday";
DaysofWeek[5] = "Friday";
DaysofWeek[6] = "Saturday";

Months = new Array( );
Months[0] = "January";
Months[1] = "February";
Months[2] = "March";
Months[3] = "April";
Months[4] = "May";
Months[5] = "June";
Months[6] = "July";
Months[7] = "August";
Months[8] = "September";
Months[9] = "October";
Months[10] = "November";
Months[11] = "December";

RightNow = new Date( );

var day = DaysofWeek[RightNow.getDay( )];
var date = RightNow.getDate( );
var Month = Months[RightNow.getMonth( )];
var Year = RightNow.getFullYear( );

if (date == 1 || date == 21 || date == 31)
{ ender = "<sup>st</sup>"; }

if (date == 2 || date == 22)
{ ender = "<sup>nd</sup>"; }

if (date == 3 || date == 23)
{ ender = "<sup>rd</sup>"; }

{ ender = "<sup>th</sup>"; }

document.write("Today is " + day + " " + Month + " " + date + ender + ", " + Year + ".");

Overview of the Script Tips #31-33 Script

As shown by the document.write( ) command at the end of the script, the outputted date string has the following 'anatomy':

"Today is " + day + " " + Month + " " + date + ender + ", " + Year + "."

day is the textual day of the week: Monday, Tuesday, etc.
Month is the textual month of the year: January, February, etc.
date is the unaltered return for the getDate( ) method of the Date object, which gives the numerical date of the month and runs normally from 1 to 31, 30, 28, or 29, as appropriate
ender is a superscripted ordinal number suffix for date: st, nd, rd, or th
Year is the unaltered return for the getFullYear( ) method of the Date object, which gives a four-digit year


Joe stringifies the textual days of the week and organizes them as an array, DaysofWeek. In order, DaysofWeek's elements run from Sunday (DaysofWeek[0]) to Saturday (DaysofWeek[6]) so that the DaysofWeek index numbers and values match the corresponding returns of the getDay( ) method of the Date object, which run from 0 for Sunday to 6 for Saturday - in Joe's words, [W]e are going to play into JavaScript's indexing system.

We can then use the getDay( ) return as a DaysofWeek index number to obtain day as the textual day of the week:

RightNow = new Date( );
var day = DaysofWeek[RightNow.getDay( )];

Suppose it's Monday, for which RightNow.getDay( ) returns 1. Plugging RightNow.getDay( ) into the square brackets of DaysofWeek[ ] thus gives DaysofWeek[1], whose value is Monday, which is assigned to day. Very logical.


As for day, so for Month. Joe stringifies the textual months of the year and organizes them as an array, Months. In order, Months's elements run from January to December so that the Months index numbers and values match the corresponding returns of the getMonth( ) method of the Date object. We then similarly use the getMonth( ) return as a Months index number to obtain Month as the textual month of the year:

var Month = Months[RightNow.getMonth( )];

Suppose it's June, for which RightNow.getMonth( ) returns 5. The Months[RightNow.getMonth( )] expression becomes in effect Months[5], whose value is June, which is assigned to Month.


A series of four if...else statements looks at date, the RightNow.getDate( ) return, and creates an appropriate superscripted suffix therefor. The conditions of the first three if branches all make use of the == comparison operator and the || logical operator - operators that we know like the backs of our hands at this point. For example, here's the first if conditional:

if (date == 1 || date == 21 || date == 31)
{ ender = "<sup>st</sup>"; }

The code above says, "If it's true that date is equal to 1 OR 21 OR 31, then superscript st and assign the result to ender." The HTML sup element is discussed here in the HTML 4.01 Specification.

Analogously, the second if conditional assigns nd to ender if date is 2 or 22 and the third if conditional assigns rd to ender if date is 3 or 23. The final else statement creates a default suffix th for all other values of date.

Other code possibilities

(1) We can in two ways significantly condense the Script Tips #31-33 Script.

(a) DaysofWeek and Months can be written as condensed arrays or array literals as described in Blog Entry #42, e.g.:

DaysofWeek = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

Months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

(b) The series of if...else statements can be shrunk to four lines of code via the strategy that we applied to the Script Tips #25-28 Script in Blog Entry #61: set the default ender first and then use if statements to set nondefault enders:

ender = "<sup>th</sup>";
if (date == 1 || date == 21 || date == 31) ender = "<sup>st</sup>";
if (date == 2 || date == 22) ender = "<sup>nd</sup>";
if (date == 3 || date == 23) ender = "<sup>rd</sup>";

(2) The HTML sup element maps onto the CSS vertical-align: super declaration, so if you are a stickler for 'separating structure and presentation' (as the W3C would want you to be), then you can (a) put, say,

.supe {vertical-align: super;}

in a header style element or in an external style sheet, and (b) recode the ender statements as

ender = "<span class='supe'>th</span>";
if (date == 1 || date == 21 || date == 31) ender = "<span class='supe'>st</span>"; // etc.

(3) In setting ender, date can, if preferred, be compared to suitable regular expressions instead of numbers:

ender = "<sup>th</sup>";

var x1 = /^(2|3)?1$/;
if (x1.test(date)) ender = "<sup>st</sup>";

var x2 = /^2?2$/;
if (x2.test(date)) ender = "<sup>nd</sup>";

var x3 = /^2?3$/;
if (x3.test(date)) ender = "<sup>rd</sup>";

(It's OK to plug date, a number, into the test( ) method of the core JavaScript RegExp object, which normally takes a string parameter; the "Data Type Conversion" section of the JavaScript 1.5 Core Guide states, JavaScript is a dynamically typed language. That means you do not have to specify the data type of a variable when you declare it, and data types are converted automatically as needed during script execution.)

A lazier approach

If I were teaching a JavaScript course, and a student asked me for a script that creates/displays a text-based date, then I have to confess that I would probably say, "Go use the toLocaleDateString( ) method." All by itself, the toLocaleDateString( ) method of the Date object comes close to reproducing the effect of the Script Tips #31-33 Script: on my iMac,

document.write(new Date( ).toLocaleDateString( ));

writes Saturday January 13 2007 to the page when using Netscape 7.02.

Without taking anything away from the instructive value of the Script Tips #31-33 Script, I find it a bit disappointing that Joe doesn't at least mention the toLocaleDateString( ) method (it's not listed in the HTML Goodies JavaScript methods keyword reference), which was implemented in JavaScript 1.0, the first version of JavaScript. But perhaps I should cut Joe some slack here - most of his readers/students are going to be PC users, and IRT's Date object page notes that the toLocaleDateString( ) method was not supported by MSIE prior to MSIE 5.5, which was released in July 2000 and after Script Tips #31-33 were written.

In the next post, we'll go over a script that displays a random, linking banner and that is only associated with Script Tip #34.



Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)