JsWorld

Date/Time Formatting

1. Purpose

Why have a custom date/time formatting class? The standard JavaScript Date class comes with three methods for producing localised date/time output, however, it has a few shortcomings:

The DateTimeFormatter class of the JsWorld library was designed specifically to address those issues.

2. Date/time formatting

To format dates and times you need to create a new jsworld.DateTimeFormatter object configured for your particular locale. The steps:

  1. Load the JsWorld classes file JsWorld.js
  2. Load the data file for your locale from the locales/js/ directory. This imports an object called POSIX_LC.<locale_code> containing the locale properties.
  3. Use the locale properties to create a new jsworld.Locale object.
  4. Use the jsworld.Locale object to create a new jsworld.DateTimeFormatter.

An example how to load the necessary files and instantiate the formatter for the de_DE (German/Germany) locale:

<!-- Load the JsWorld classes -->
<script type="text/javascript" src="JsWorld.js"></script>

<!-- Load the de_DE locale definition object "POSIX_LC.de_DE" -->
<script type="text/javascript" src="locales/js/de_DE.js"></script>

<script type="text/javascript">

	// Create new date/time formatter for the de_DE locale
	var lc = new jsworld.Locale(POSIX_LC.de_DE)
	var dtf = new jsworld.DateTimeFormatter(lc);

</script>

Now you're ready to format dates and times. To do that you just need to pass a Date object or an ISO-8601 date/time string to the appropriate format method:

Let's try out the three methods using the current date as an argument:

// get the current date/time
var now = new Date();

// show the time
document.writeln(dtf.formatTime(now));

// show the date
document.writeln(dtf.formatDate(now));

// show the combined time and date
document.writeln(dtf.formatDateTime(now));

Here is the example output:

22:45:15
21.11.09
21. November 2009 22:45:15

Let's now invoke the same three methods, but with a ISO-8601 formatted date/time string. This format is commonly used to pass date/time-related data from back-end databases and services.

var isoDateTime = "2009-11-21 22:45:15";

// show the time
document.writeln(dtf.formatTime(isoDateTime));

// show the date
document.writeln(dtf.formatDate(isoDateTime));

// show the combined time and date
document.writeln(dtf.formatDateTime(isoDateTime));

The resulting output:

22:45:15
21.11.09
21. November 2009 22:45:15

3. Helper methods

The jsworld.Locale class offers four helper methods to retrieve the locale's weekday and month names.

You can use these methods for tasks such as generating weekday/month form input elements or providing localised date info about events.

For example:

// Create en_US locale object (American English/US)
var lc_en = new jsworld.Locale(POSIX_LC.en_US);

// Create pt_BR locale object (Portuguese/Brazil)
var lc_pt = new jsworld.Locale(POSIX_LC.pt_BR);

// Print the month names in both languages
for (var i=0; i < 12; i++) {
	var month_en = lc_en.getMonthName(i);	
	var month_pt = lc_pt.getMonthName(i);

	document.writeln(i+1 + ". " + month_en + " : " + month_pt);
}

// Print the current weekday in English and Portuguese
var today = new Date().getDay();

document.writeln("Today is " + lc_en.getWeekdayName(today));
document.writeln("Hoje é " + lc_pt.getWeekdayName(today));	

The example output:

1.  January   : janeiro
2.  February  : fevereiro
3.  March     : março
4.  April     : abril
5.  May       : maio
6.  June      : junho
7.  July      : julho
8.  August    : agosto
9.  September : setembro
10. October   : outubro
11. November  : novembro
12. December  : dezembro

Today is Sunday
Hoje é domingo

4. Exception handling

The JsWorld classes normally raise an exception if an error condition is encountered. The typical such cases are:

To check for and handle such conditions use a try-catch statement:

try {
	var lc = new jsworld.Locale(POSIX_LC.en_US);
	var dtf = new jsworld.DateTimeFormatter(lc);
	dtf.formatDate(1999);
	
} catch (error) {
	document.write(error);
}

The above example will throw an error indicating an invalid argument to the format method:

Error: Invalid date argument, must be a Date object or an ISO-8601 date/time string

5. The locale properties defining date/time formatting

The POSIX LC_TIME standard is used to specify how to format dates and times in a particular locale. The standard defines a set of properties, which are used to configure the behaviour of the jsworld.DateTimeFormatter. Here is an outline of the LC_TIME properties relevant to the JsWorld implementation and their meaning (the standard defines a few more which aren't implemented by this library):

Property Description
abday defines the abbreviated weekday names
day defines the full weekday names
abmon defines the abbreviated month names
mon defines the full month names
d_t_fmt defines the behaviour of the formatDateTime() method
d_fmt defines the behaviour of the formatDate() method
t_fmt defines the behaviour of the formatTime() method
am_pm defines the ante-meridiem and post-meridiem strings

The properties are explained in detail in the POSIX LC_TIME specification. For abday, day, abmon, mon and am_pm jsworld.DateTimeFormatter can also accept an alternative JavaScript array notation instead of the standard delimited strings, which are somewhat less convenient in a JavaScript context. Make sure you read the jsworld.Locale API doc before modifying an existing locale definition or creating a new one from scratch.

The d_t_fmt, d_fmt and t_fmt properties are represented by strings containing so called conversion specifications (or placeholders) and regular characters. Let's get the t_fmt string for the en_US locale (assuming that the locale definition has been previously loaded):

// Print the t_fmt property of the en_US locale
document.writeln("POSIX_LC.en_US.t_fmt = " + POSIX_LC.en_US.t_fmt);

You should get

POSIX_LC.en_US.t_fmt = %I:%M:%S %p

Notice the placeholders, designated by a "%" followed by a character. The above t_fmt string configures the behaviour of the formatTime() method. Let's test that:

var lc = new jsworld.Locale(POSIX_LC.en_US);
var dtf = new jsworld.DateTimeFormatter(lc);

var t = "1999-12-31 23:59:59";

document.writeln(dtf.formatTime(t));

The script produces

11:59:59 PM

which lets us infer that "%I" corresponds to the hour, "%M" to the minute, "%S" to the second, and "%p" whether the time is "a.m." or "p.m."

Here is a list of all conversion specifications understood by the format methods and what they stand for:

Placeholder Description
%a replaced by the locale's abbreviated weekday name
%A replaced by the locale's full weekday name
%b replaced by the locale's abbreviated month name
%B replaced by the locale's month name
%d replaced by the day of the month as a decimal number [01..31]
%e replaced by the day of the month as a decimal number [1..31], leading space pad
%F equivalent to %Y-%m-%d (ISO-8601 date format)
%h equivalent to %b
%H replaced by the hour (24-h clock) as a decimal number [00...23]
%I replaced by the hour (12-h clock) as a decimal number [01..12]
%k replaced by the hour (24-h clock) as a decimal number [0..23]
%l replaced by the hour (12-h clock) as a decimal number [1..12]
%m replaced by the month as a decimal number [01..12]
%M replaced by the minute as a decimal number [00..59]
%n replaced by a new line
%p replaced by the locale's equivalent of either a.m. or p.m.
%P same as %p but forced lower case
%R equivalent to %H:%M
%S replaced by the second as a decimal number [00..59]
%T equivalent to %H:%M:%S
%w replaced by the weekday as a decimal number [0..6]
%y replaced by the last two digits of the year as a decimal number [00..99]
%Y replaced by the year as a decimal number (e.g. 2009)
%Z timezones not supported at present
%% replaced by %

How to customise formatting? There are two ways:

Continuing with the previous example, here is how you can redefine the formatting of times in the en_US locale:

// Redefine time formatting
POSIX_LC.en_US.t_fmt = "%Hh %Mm %Ss";

// Create a new formatter
var dtf = new jsworld.DateTimeFormatter(new jsworld.Locale(POSIX_LC.en_US));

// Print time
document.writeln(dtf.formatTime("1999-12-31 23:59:59"));

Now, instead of "11:59:59 PM" you will see this:

23h 59m 59s

6. Examples

All examples presented in this manual can be found here.

7. API documentation

Auto-generated documentation for the DateTimeFormatter class is available here.