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.min.js
  2. Load the properties 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.min.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:

The variant argument is optional. You can use it to get alternative shorter or longer formatting instead of the default one (no variant), provided the locale properties have these variants defined (*_full, *_long, etc):

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
am_pm defines the ante-meridiem and post-meridiem strings
d_t_fmt defines the default output of formatDateTime(date) (no variant)
d_t_fmt_full optional, defines the output of formatDateTime(date, "full")
d_t_fmt_long optional, defines the output of formatDateTime(date, "long")
d_t_fmt_medium optional, defines the output of formatDateTime(date, "medium")
d_t_fmt_short optional, defines the output of formatDateTime(date, "short")
d_fmt defines the default output of formatDate(date) (no variant)
d_fmt_full optional, defines the output of formatDate(date, "full")
d_fmt_long optional, defines the output of formatDate(date, "long")
d_fmt_medium optional, defines the output of formatDate(date, "medium")
d_fmt_short optional, defines the output of formatDate(date, "short")
t_fmt defines the default output of formatTime(date) (no variant)
t_fmt_full optional, defines the output of formatTime(date, "full")
t_fmt_long optional, defines the output of formatTime(date, "long")
t_fmt_medium optional, defines the output of formatTime(date, "medium")
t_fmt_short optional, defines the output of formatTime(date, "short")

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.