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 locale of the web page and user's browser (and OS) may not be the same.
- The
Date
class is typically browser and OS dependent and the formatting for a particular locale may vary across implementations. - You may want to define your own local date/time formatting.
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:
- Load the JsWorld classes file
JsWorld.min.js
- Load the properties file for your locale from the
locales/js/
directory. This imports an object calledPOSIX_LC.<locale_code>
containing the locale properties. - Use the locale properties to create a new
jsworld.Locale
object. - Use the
jsworld.Locale
object to create a newjsworld.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:
formatDate(date, variant)
to format a date valueformatTime(date, variant)
to format a time valueformatDateTime(date, variant)
to format a combined date/time value
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):
variant = "full"
to use a full formatting patternvariant = "long"
to use a long formatting patternvariant = "medium"
to use a medium formatting patternvariant = "short"
to use a short formatting pattern
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.
getWeekdayName(weekdayNum)
returns the name of the specified weekdaygetAbbreviatedWeekdayName(weekdayNum)
returns the abbreviated name of the specified weekdaygetMonthName(monthNum)
returns the name of the specified monthgetAbbreviatedMonthName(monthNum)
returns the abbreviated name of the specified month
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:
- Invalid or missing locale property
- Invalid argument to the format or helper methods
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:
- For minor changes you can simply redefine the appropriate locale property
- For something much more customised you could write your own locale definition from scratch
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.