Skip to content

Instantly share code, notes, and snippets.

@mattbaggott
Last active October 14, 2015 00:18
Show Gist options
  • Save mattbaggott/4278541 to your computer and use it in GitHub Desktop.
Save mattbaggott/4278541 to your computer and use it in GitHub Desktop.
Short demo on successfully working with timezones in R
##
## Sample code to teach about timezones in R
## matt@baggott.net
## Dec 13, 2012
## Time zones are important to understand when working with dates
## because the most common date class for R, POSIX, is actually a date/time
## class. (POSIX = "Portable Operating System Interface,
## an IEEE standard)
##
## Key points:
##
## POSIX dates without times are considered midnight.
## POSIX dates without timezones are considered local timezone.
## Some Unix-like systems (especially Linux ones) do not have environment
## variable TZ set and you need to set it
## Base R contains POSIXct, POSIXlt, and Date classes.
## -ct is a numeric vector
## -lt is a named list
## Date is a numeric vector, intended to be integers - this is not enforced
## Time zone names depend on your OS and giving an illegal TZ name will
## sometimes fail silently (i.e., it will use "UTC")
## While there is no safe universal TZ name list and we should minimize TZ names in
## code, "Country/City" list below is widely used (including in R in Windows):
## http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
#########################################
## Getting basic information from system
## empty time zone and wrong dates and times can cause huge headaches
# get your time zone
Sys.timezone()
# if you lack one, you can Sys.setenv(TZ="America/Chicago") or whatever
# get current date + time
Sys.time()
# get current day in the current timezone
Sys.Date()
# get many details about current locale
Sys.getlocale()
#########################################
## Is time zone explicitly stored with time? (Answer: not necessarily)
## If not, what happens? Let's find out. (Answer: local one is used)
# Let's create a time 10 seconds after 1960-01-01 00:00:00 GMT
# (the origin used by SAS; "GMT" is Greenwich Mean Time )
t <- as.POSIXct(10, origin="1960-01-01", tz="GMT") # tzone IS given
attributes(t) # Yes explicit tzone
t <- as.POSIXct(10, origin="1960-01-01") # note tzone NOT given
attributes(t) # No explicit tzone, is assuming Sys.timezone()
# and you can see from ?as.POSIXct that the default for tz="" is local time
#########################################
## POSIXct, stores seconds since origin
## vs
## POSIXlt, stores list
## vs
## Date
# we have been making objects of class "POSIXct" "POSIXt"
class(t)
# ct, as before
t <- as.POSIXct(10, origin="1960-01-01", tz="GMT")
attributes(t) # tzone and class, as before
# lt
t <- as.POSIXlt(10, origin="1960-01-01", tz="GMT")
attributes(t) # list of names and tzone and class
# Sys.time() will provide explicit tzone to lt but not ct
(now <- as.POSIXlt(Sys.time())) # current datetime, note POSIX- lt not ct
attributes(now) # Yes, contains attribute tzone
(now <- as.POSIXct(Sys.time())) # current datetime, note POSIX- lt not ct
attributes(now) # No attribute tzone
# We can include time in origin
(t <- as.POSIXct(10, origin="1960-01-01 10:00:00"))
# Dates without times are treated as being at midnight
(t <- as.POSIXct("1970-01-01", origin="1960-01-01"))
(t - 1) # subtract a second, changes date
# this means timezone errors can easily change dates!
# If you don't need time, may be safer to use Date objects instead of POSIX
(t <- as.Date("1970-01-01", origin="1960-01-01")) # save as Date
class(t) # now class is Date, no time headaches
attributes(t) # only class
#########################################
## What time zone names should I use? (as few as possible)
##
## http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
# Because TZ is handled by the system, not R, no one can guarantee a given
# tz name will work, but Olson's list of Location/Country strings usually
# works. http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
# A common recommendation is to store as UTC (Universal Time, Coordinated)
# which you might call physical time, and convert to
# user/local/civil time as needed, but this is not always appropriate
# for human generated data.
# Differences btwn "Greenwich Mean Time" and "Universal Time, Coordinated"
# can usually be ignored
#########################################
## Conversions
##
## When it is time t here, what time is it there?
# If your input has tz info, use POSIXlt
t <- Sys.time() #here
as.POSIXlt(t, tz = 'America/Barbados') #there
# You must use lt for this as as.POSIXct will use tz info from Sys.time()
#or for a succinct ct representation
as.POSIXct(as.POSIXlt(t, tz = 'America/Barbados'))
# You can also format it as a string with that tz
(y <- format(t, tz="America/Barbados", usetz=TRUE))
class(y)
#########################################
## Additional notes
##
## my next demo shows how to make circular 24-hour plots
## https://gist.github.com/4361381
## for more on timezones see these helpful resources
## http://blog.revolutionanalytics.com/2009/06/converting-time-zones.html
## http://stackoverflow.com/questions/2532729/daylight-saving-time-and-timezone-best-practices
## lubridate package is a user friendly way to work with time/date and
## generally fast (because it uses regular expressions)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment