Crossing Time Zones With ASE

DATA MANAGEMENT
Crossing Time Zones With ASE
Solving the Time Zone Translation Problem
Working with timestamped data in ASE can be challenging as there is
little information and few coded solutions for translating data from one
time zone to another. In this article, I will explain how to implement time
translations across multiple time zones.
By Mark Gearhart
I
f you find yourself juggling
time zones, you are not alone.
I am currently in contact with
clients in UTC -4, +1, +8, +3, and
-5 (i.e. New York, London, Hong
Kong, Moscow, and Houston),
although it varies with the projects
I’m working on at any given time.
If you add daylight savings time to
the mix, it gets even more interesting.
A frequent exercise usually involves
computing the difference in time, between, say Hong Kong and New York
in order to schedule a time for a conference call. Another common scenario
is figuring out what time it is in Sydney
when the markets close on Friday at
4PM in New York. The result is, not
surprisingly, a decision to let my colleague sleep at 6AM Saturday morning
rather then wake him for a question.
Mark Gearhart is an independent Systems
Engineer, currently based in Research
Triangle Park, North Carolina. He
develops databases and rich internet
applications for temporal and realtime
systems. His background encompasses
the energy and financial industries
with a special interest in data storage
architectures and fast user interfaces.
He is currently working on projects with
Dobler Consulting and can be reached at
www.mgearhart.com.
50
ISUG TECHNICAL JOURNAL
The Problem
If you are writing applications which
likewise deal with times around the
globe, there is little information and
very few coded solutions for translating
data from one time zone to another. In
Sybase ASE, the bigdatetime, datetime
and smalldatetime data types do not
store time zone information and
the products are entirely unaware
of the concepts of time zones
and daylight savings time. Sybase
Servers only recognize and store
the date and time portions of the
values provided by the operating system, which are based on
the time zone configured at the
operating system level. Therefore,
if you work with timestamped
data in ASE, you must solve time
translation problems yourself.
Coordinated Universal Time
If we start by thinking about
Coordinated Universal Time
(UTC) time as a common point
of reference, then times can be
compared. For example, in a
scheduling application, when a user
in New York enters a time for a
conference call with a colleague
in Hong Kong, he types 2011-0519 09:00 EDT. The application
converts this to UTC time and
stores 2011-05-19 14:00 UTC in
the database. On the other side of
the world, the user in Hong Kong
checks the time of the meeting.
The application reads the time
from the database. It still represents 2011-05-19 14:00 UTC, but
based on Hong Kong’s time zone,
the time is returned as 2011-05-19
21:00 HKT. Therefore, knowing
that time is stored as UTC turns
the entire problem into a simple
calculation from New York time
(UTC-5 hours) to UTC and then
from UTC to Hong Kong time
CROSSING TIME ZONES WITH ASE
(UTC+8 hours). Based on this general approach, a user in
Frankfurt knows that he can join the same call at his local
time of 2011-05-19 14:00 CEST.
UTC time is the key to translating time zones. UTC time
represents the physical world; therefore, time neither reverses
nor does it skip as in the case of local time, which can have
23, 24, or 25 hours days. There are no daylight savings adjustments, and therefore data stored in UTC time guarantees
uniqueness. In UTC time, there are always 24 hours in a day.
For any location in the world, the local time can be calculated by adding or subtracting a certain number of minutes
which may vary from one day to the next depending on the
daylight savings time adjustment.
The Solution
So, how do we implement time translation so we can convert
between local and UTC time? Do we extend the datetime
data type to include a time zone? Do we write some kind of
layered API? Do we invent a database solution using time
translation tables which supply offsets to UTC time?
I have found that the last option presents a viable and
simple solution, and is well worth trying. For this option, we
can begin by constructing two static lookup tables as follows:
cre at e t abl e T i meZon e (
Z o n e s m al l i n t not nu ll,
Nam e v arc h ar ( 50 ) not nu ll)
UTCStart
UTCStop
DST
Offset
Abbr
4
2010-11-07 08:00:00.000
2011-03-13 06:59:59.997
““
-300
EST
4
2011-03-13 07:00:00.000
2011-11-06 06:59:59.997
““
-240
EDT
4
2011-11-06 07:00:00.000
2011-11-06 07:59:59.997
“2“
-300
EST
4
2011-11-06 07:00:00.000
2012-03-11 06:59:59.997
““
-300
EST
Table 2: TimeTran
UTC-to-local time translations are performed according
to the interval and offset configured for the time in question. For the U.S. Eastern time zone, which encompasses
America/New_York, the time translation for the spring and
fall daylight savings time intervals would proceed as shown in
Table 3.
For this UTC
Time
Add
this
offset
To produce this local
time
And this
DST
And this
Zone
2011-03-13 05:00
-300
2011-03-13 00:00
““
EST
2011-03-13 06:00
-300
2011-03-13 01:00
““
EST
2011-03-13 07:00
-240
2011-03-13 03:00
““
EDT
2011-03-13 08:00
-240
2011-03-13 04:00
““
EDT
2011-11-06 04:00
-240
2011-11-06 00:00
““
EDT
2011-11-06 05:00
-240
2011-11-06 01:00
““
EDT
2011-11-06 06:00
-240
2011-11-06 02:00
““
EDT
2011-11-06 07:00
-300
2011-11-06 02:00
“2”
EST
2011-11-06 08:00
-300
2011-11-06 03:00
““
EST
Table 3: UTC-to-Local Time Translation
cre at e t abl e T i meT r a n (
Z o n e s m al l i n t not nu ll,
U TCS t art dat etim e n ot nu ll,
U TCS t o p d at e t im e n ot nu ll,
D S T c h ar(1 ) n o t nu ll,
Of f s e t s m al l i n t not nu ll,
A bbr c h ar(5 ) not nu ll)
The TimeZone table (see
Table 1) contains a list of time
zones. We will concentrate on just
one time zone, called America/
New_York as it is known from the
public domain TZ (or Olson) data
source.
Zone
Zone
Name
0
UTC
1
Europe/London
3
Europe/Moscow
4
America/New_York
8
Australia/Sydney
Table 1: TimeZone
The TimeTran table (see Table 2) contains the offsets
from UTC time for each time zone listed in the TimeZone
table. The TimeTran table has a row for every resetting of
the clock. For America/New_York, this gives us a table with
4 rows per year.
Westward Expansion
As time zones move westward to increase UTC time, the
offset also increases. This preserves the relative time of the
data with respect to the time at which it was stored in the
database. Once the offset has been configured, data may be
selected by converting the UTC time stored with the data
into a local time. To automate things a bit, we can create
functions which convert from UTC time to local time and
visa versa. The utctoloc function takes UTC time as input and
returns the corresponding local time and DST indicator as
output. The loctoutc function is the reverse of utctoloc. It takes
the local time and DST indicator as input and returns the
corresponding UTC time as output. For the spring daylight
savings time interval in the U.S., we consider the local 2 AM
hour as being non-existent. Therefore if this hour is passed in,
the UTC time is returned as null:
cr ea t e funct ion ut ct oloc(@U t c d a t et me, @Z one
sma llint ) r et ur ns d a t et ime a s
beg in
r et ur n (select d a t ea d d (mi,O ffset ,@U t c)
fr om T imeT r a n
w her e @U t c >= U T CS t a r t
APRIL - JUNE 2011
51
CROSSING TIME ZONES WITH ASE
an d @ U t c < = U T C Stop
an d Z o n e = @Zon e)
en d
cre at e f un c t i o n l octou tc( @ L oc d a tetm e, @ Ds t cha r (1 ),
@Z o n e s m al l i n t ) r etu r n s d a tetim e a s
begin
re t u rn (s e l e c t d a tea d d ( m i, - O ffs et, @ L oc)
f ro m T i m e Tra n
w h e re UT CS t a r t < d a tea d d ( m i, - O ffs et, @ L oc)
an d U TCS t o p > = d a tea d d ( m i, - O ffs et, @ L oc)
an d D S T = @ D s t
an d Z o n e = @Zon e)
en d
Using these functions, we can perform time arithmetic
between local times in different time zones. For example, the
query below will show that, on May 19th, 2011, there are 14
hours between Sydney and New York (for other dates there
may be a 13 or 15 hour difference depending on daylight
savings time):
se l e c t Ho urs = d a ted iff( hh,
(s e l e c t dbo .l o c tou tc( “ 20 1 1 - 05 - 19 ” , ” “ , Zon e)
f ro m Ti m e Z o ne wher e N a m e = “ A u s tr a lia / Syd ney”),
(s e l e c t dbo .l o c tou tc( “ 20 1 1 - 05 - 19 ” , ” “ , Zon e)
f ro m Ti m e Z o ne wher e N a m e = “ A m er ica / N ew _ Y or k”))
We can also use local time as a search argument to translate data stored in UTC time into any desired local time. For
example,the following query will select a day’s worth of data
for the America/ New_York time zone. Since November 7th,
2011 crosses the fall daylight savings time interval, the query
automatically returns 25 hours of data:
se l e c t
U TCTi m e = d .U T C T im e,
L o c Ti m e = d at ea d d ( m i, O ffs et, d . U T C T im e) ,
HE = ri g h t (“ 0 ” + conv er t( v a r cha r ( 2 ) , d a tep a r t(hh,
dat e add(m s, - 2 , d a tea d d ( m i, t. O ffs et, d . U T CT ime)))
+ 1 , 2 ),
D S T = t .D S T ,
A bbr = t .A bbr,
V al u e = d.V al u e
fro m D at a d, Ti meT r a n t, T im eZone z
w h e re d.UT CTi me > = t. U T C Sta r t
an d d.UT CTi m e < = t. U T C Stop
an d t .Z o n e = z.Zone
an d d.UT CTi m e > d b o. loctou tc( “ 20 1 1 - 11 - 06 ” , ” “,z. Z one)
an d d.UT CTm e < = d b o. loctou tc( “ 20 1 1 - 11 - 07 ” ,” “,z. Z one)
an d z.N am e = “ Am er ica / N ew_ Y or k ” )
o rd e r by d.UT CTim e
52
ISUG TECHNICAL JOURNAL
The output of this query (see Table 4) demonstrates that we
have:
• Converted local to UTC time in the search arguments
in order to locate data which is stored in UTC time.
• Converted the returned data to the appropriate local
time.
• Displayed a repeated 2 AM hour.
• Displayed the correct EDT/EST time zone for each hour.
• Displayed a nice hour-ending time from 1 through 24.
UTCTime
LocTime
HE
DST
Abbr
Value
2011-11-06 05:00
2011-11-06 01:00
2011-11-06 06:00
2011-11-06 02:00
01
EDT
456
02
EDT
684
2011-11-06 07:00
2011-11-06 02:00
02
EST
123
2011-11-06 08:00
2011-11-06 03:00
03
EST
234
2011-11-06 09:00
2011-11-06 04:00
04
EST
768
2011-11-06 10:00
2011-11-06 05:00
05
EST
345
2011-11-06 11:00
2011-11-06 06:00
06
EST
456
2011-11-06 12:00
2011-11-06 07:00
07
EST
546
2011-11-06 13:00
2011-11-06 08:00
08
EST
234
2011-11-06 14:00
2011-11-06 09:00
09
EST
345
2011-11-06 15:00
2011-11-06 10:00
10
EST
838
2011-11-06 16:00
2011-11-06 11:00
11
EST
155
2011-11-06 17:00
2011-11-06 12:00
12
EST
947
2011-11-06 18:00
2011-11-06 13:00
13
EST
258
2011-11-06 19:00
2011-11-06 14:00
14
EST
783
2011-11-06 20:00
2011-11-06 15:00
15
EST
145
2011-11-06 21:00
2011-11-06 16:00
16
EST
555
2011-11-06 22:00
2011-11-06 17:00
17
EST
456
2011-11-06 23:00
2011-11-06 18:00
18
EST
754
2011-11-07 00:00
2011-11-06 19:00
19
EST
174
2011-11-07 01:00
2011-11-06 20:00
20
EST
358
2011-11-07 02:00
2011-11-06 21:00
21
EST
678
2011-11-07 03:00
2011-11-06 22:00
22
EST
264
2011-11-07 04:00
2011-11-06 23:00
23
EST
457
2011-11-07 05:00
2011-11-07 00:00
24
EST
256
2
Table 4: Query Output
Conclusion
With this, the data engineer can appreciate the fact that time
zone configurations have been placed into a very manageable
spot inside the database to be used with all the other data.
New entries can be added for historic or future data, and with
a small amount SQL code, both time zone arithmetic and
time translation across time zones can be implemented when
the opportunity arises.