Permalink
Newer
Older
100644 172 lines (106 sloc) 9.55 KB
May 4, 2012
1
# TimezoneJS.Date
2
3
[![Build Status](https://secure.travis-ci.org/mde/timezone-js.png)](https://secure.travis-ci.org/mde/timezone-js)
4
May 4, 2012
5
A timezone-enabled, drop-in replacement for the stock JavaScript Date. The `timezoneJS.Date` object is API-compatible with JS Date, with the same getter and setter methods -- it should work fine in any code that works with normal JavaScript Dates.
6
7
[Mailing list](http://groups.google.com/group/timezone-js)
8
9
## Overview
10
11
The `timezoneJS.Date` object gives you full-blown timezone support, independent from the timezone set on the end-user's machine running the browser. It uses the Olson zoneinfo files for its timezone data.
12
13
The constructor function and setter methods use proxy JavaScript Date objects behind the scenes, so you can use strings like '10/22/2006' with the constructor. You also get the same sensible wraparound behavior with numeric parameters (like setting a value of 14 for the month wraps around to the next March).
14
15
The other significant difference from the built-in JavaScript Date is that `timezoneJS.Date` also has named properties that store the values of year, month, date, etc., so it can be directly serialized to JSON and used for data transfer.
16
17
## Setup
18
19
First you'll need to include the code on your page. Both `timezoneJS.Date`, and the supporting code it needs in `timezoneJS.timezone` are bundled in the `date.js` file in `src` directory. Include the code on your page with a normal JavaScript script include, like so:
20
21
<script type="text/javascript" src="/js/timezone-js/src/date.js">
22
23
Next you'll need the Olson time zone files -- `timezoneJS.Date` uses the raw Olson data to calculate timezone offsets. The Olson region files are simple, structured text data, which download quickly and parse easily. (They also compress to a very small size.)
24
25
Here is an example of how to get the Olson time zone files:
26
27
##!/bin/bash
28
29
# NOTE: Run from your webroot
30
31
# Create the /tz directory
32
mkdir tz
33
34
# Download the latest Olson files
35
curl ftp://ftp.iana.org/tz/tzdata-latest.tar.gz -o tz/tzdata-latest.tar.gz
36
37
# Expand the files
38
tar -xvzf tz/tzdata-latest.tar.gz -C tz
39
40
# Optionally, you can remove the downloaded archives.
41
rm tz/tzdata-latest.tar.gz
May 4, 2012
43
Then you'll need to make the files available to the `timezoneJS.timezone` code, and initialize the code to parse your default region. (This will be North America if you don't change it). No sense in downloading and parsing timezone data for the entire world if you're not going to be using it.
44
45
Put your directory of Olson files somewhere under your Web server root, and point `timezoneJS.timezone.zoneFileBasePath` to it. Then call the init function. Your code will look something like this:
46
47
timezoneJS.timezone.zoneFileBasePath = '/tz';
48
timezoneJS.timezone.init();
49
Jun 17, 2012
50
If you use `timezoneJS.Date` with `Fleegix.js`, there's nothing else you need to do -- timezones for North America will be loaded and parsed on initial page load, and others will be downloaded and parsed on-the-fly, as needed. If you want to use this code with some other JavaScript toolkit, you'll need to overwrite your own transport method by setting `timezoneJS.timezone.transport = someFunction` method. Take a look at `test-utils.js` in `spec` for an example.
May 4, 2012
51
52
## Usage
53
54
Create a `timezoneJS.Date` the same way as a normal JavaScript Date, but append a timezone parameter on the end:
55
56
var dt = new timezoneJS.Date('10/31/2008', 'America/New_York');
57
var dt = new timezoneJS.Date(2008, 9, 31, 11, 45, 'America/Los_Angeles');
58
59
Naturally enough, the `getTimezoneOffset` method returns the timezone offset in minutes based on the timezone you set for the date.
60
61
// Pre-DST-leap
62
var dt = new timezoneJS.Date(2006, 9, 29, 1, 59, 'America/Los_Angeles');
63
dt.getTimezoneOffset(); => 420
64
// Post-DST-leap
65
var dt = new timezoneJS.Date(2006, 9, 29, 2, 0, 'America/Los_Angeles');
66
dt.getTimezoneOffset(); => 480
67
68
Just as you'd expect, the getTime method gives you the UTC timestamp for the given date:
69
70
var dtA = new timezoneJS.Date(2007, 9, 31, 10, 30, 'America/Los_Angeles');
71
var dtB = new timezoneJS.Date(2007, 9, 31, 12, 30, 'America/Chicago');
72
// Same timestamp
73
dtA.getTime(); => 1193855400000
74
dtB.getTime(); => 1193855400000
75
76
You can set (or reset) the timezone using the `setTimezone` method:
77
78
var dt = new timezoneJS.Date('10/31/2006', 'America/Juneau');
79
dt.getTimezoneOffset(); => 540
80
dt.setTimezone('America/Chicago');
81
dt.getTimezoneOffset(); => 300
82
dt.setTimezone('Pacific/Honolulu');
83
dt.getTimezoneOffset(); => 600
84
85
The getTimezone method tells you what timezone a `timezoneJS.Date` is set to.
86
87
var dt = new timezoneJS.Date('12/27/2010', 'Asia/Tokyo');
88
dt.getTimezone(); => 'Asia/Tokyo'
89
90
## Customizing
91
92
If you don't change it, the timezone region that loads on
93
initialization is North America (the Olson 'northamerica' file). To change that to another reqion, set `timezoneJS.timezone.defaultZoneFile` to your desired region, like so:
94
95
timezoneJS.timezone.zoneFileBasePath = '/tz';
96
timezoneJS.timezone.defaultZoneFile = 'asia';
97
timezoneJS.timezone.init();
98
99
If you want to preload multiple regions, set it to an array, like this:
100
101
timezoneJS.timezone.zoneFileBasePath = '/tz';
102
timezoneJS.timezone.defaultZoneFile = ['asia', 'backward', 'northamerica', 'southamerica'];
103
timezoneJS.timezone.init();
104
105
By default the `timezoneJS.Date` timezone code lazy-loads the timezone data files, pulling them down and parsing them only as needed.
106
107
For example, if you go with the out-of-the-box setup, you'll have all the North American timezones pre-loaded -- but if you were to add a date with a timezone of 'Asia/Seoul,' it would grab the 'asia' Olson file and parse it before calculating the timezone offset for that date.
108
109
You can change this behavior by changing the value of `timezoneJS.timezone.loadingScheme`. The three possible values are:
110
111
1. `timezoneJS.timezone.loadingSchemes.PRELOAD_ALL` -- this will preload all the timezone data files for all reqions up front. This setting would only make sense if you know your users will be using timezones from all around the world, and you prefer taking the up-front load time to the small on-the-fly lag from lazy loading.
112
2. `timezoneJS.timezone.loadingSchemes.LAZY_LOAD` -- the default. Loads some amount of data up front, then lazy-loads any other needed timezone data as needed.
113
3. `timezoneJS.timezone.loadingSchemes.MANUAL_LOAD` -- Preloads no data, and does no lazy loading. Use this setting if you're loading pre-parsed JSON timezone data.
114
115
## Pre-Parsed JSON Data
116
117
If you know beforehand what specific cities your users are going to be using, you can reduce load times specifically by creating a pre-parsed JSON data file containing only the timezone info for those specific cities.
118
Jun 17, 2012
119
The src directory contains 2 command-line JavaScript scripts that can generate this kind of JSON data:
120
121
- `node-preparse.js`: Uses Node to preparse and populate data.
122
- `preparse.js`: This script requires the Rhino (Java) JavaScript engine to run, since the stock SpiderMonkey (C) engine doesn't come with file I/O capabilities.
May 4, 2012
123
124
Use the script like this:
125
126
rhino preparse.js zoneFileDirectory [exemplarCities] > outputfile.json
127
Jun 17, 2012
128
Or:
129
130
node node-preparse.js zoneFileDirectory [exemplarCities] > outputfile.json
131
May 4, 2012
132
The first parameter is the directory where the script can find the Olson zoneinfo files. The second (optional) param should be a comma-delimited list of timzeone cities to create the JSON data for. If that parameter isn't passed, the script will generate the JSON data for all the files.
133
134
rhino preparse.js olson_files \
135
"Asia/Tokyo, America/New_York, Europe/London" \
136
> major_cities.json
137
138
rhino preparse.js olson_files > all_cities.json
Jun 17, 2012
139
Or:
140
141
node node-preparse.js olson_files \
142
"Asia/Tokyo, America/New_York, Europe/London" \
143
> major_cities.json
May 4, 2012
144
Jun 17, 2012
145
node node-preparse.js olson_files > all_cities.json
146
May 4, 2012
147
Once you have your file of JSON data, set your loading scheme to `timezoneJS.timezone.loadingSchemes.MANUAL_LOAD`, and load the JSON data with `loadZoneJSONData`, like this:
148
149
var _tz = timezoneJS.timezone;
150
_tz.loadingScheme = _tz.loadingSchemes.MANUAL_LOAD;
151
_tz.loadZoneJSONData('/major_cities.json', true);
152
Jun 17, 2012
153
Since the limited set of data will be much smaller than any of the zoneinfo files, and the JSON data is deserialized with `eval` or `JSON.parse`, this method is significantly faster than the default setup. However, it only works if you know beforehand exactly what timezones you want to use.
May 4, 2012
154
155
## Compressing
156
157
The Olson timezone data files are simple, space- and linefeed-delimited data. The abundance of whitespace means they compress very, very well.
158
159
If you plan to use `timezoneJS.Date` in a production Web app, it's highly recommended that you first strip the copious comments found in every Olson file, and serve compressed versions of the files to all browsers that can handle it. **(Note that IE6 reports itself as able to work with gzipped data, but has numerous problems with it.)**
160
161
Just to give you an idea of the difference -- merely stripping out the comments from the 'northamerica' file reduces its size by two-thirds -- from 103K to 32K. Gzipping the stripped file reduces it down to 6.5K -- probably smaller than most of the graphics in your app.
162
163
The `src` directory has a sample Ruby script that you can use to strip comments from Olson data files.
164
166
This project use [Jake](https://github.com/mde/jake) to build. In order to see available tasks, do `jake -T`. The build sequence is:
May 4, 2012
167
168
- `jake test:init`: Download and extract tz files to `lib/tz`.
169
- `jake test`: Run `jasmine-node`.
171
Feel free to fork and modify at your own will.
172
The source code is annotated and doc can be generated with `jake doc`.