We all know what a nightmare dates and times in R can be. I don’t know exactly how many scripts I have lying around my hard drive that consist entirely of trying different ways to get a single column into the correct date/time format, but if those scripts were bottles of wine, I’d be my lab’s Sommelier.

One of the main issues I have is that all my data are collected in Pacific Standard Time (PST), and must be converted to Universal Coordinated Time (UTC) before I can upload them to our central database. The first thing to do is make sure that my R session is in PST, and, if it’s not, put it there. The hilarious thing about this is that lubridate doesn’t recognize “PST” as a time zone - so I have to substitute “Pacific/Pitcairn” because it’s one of the only timezones that uses GMT -8 and doesn’t adjust for Daylight Savings Time. Shhhhh.

Sys.timezone(location=FALSE)
## [1] NA
Sys.setenv(TZ='Pacific/Pitcairn')
Sys.timezone()
## [1] "Pacific/Pitcairn"


Cool. Okay, then I load my dataframe “d” with the column of values to be transformed, Start_DatePST:

library(lubridate)

# build example dataframe
d <- as.data.frame(cbind(Location = rep("wallace_weir", 3), Start_DatePST = c('2013-09-23 11:19:00', '2014-03-18 09:56:00', '2014-08-28 09:25:00')))

# convert date column to POSIXct
d$Start_DatePST <- ymd_hms(d$Start_DatePST) 
d
##       Location       Start_DatePST
## 1 wallace_weir 2013-09-23 11:19:00
## 2 wallace_weir 2014-03-18 09:56:00
## 3 wallace_weir 2014-08-28 09:25:00


Since the default time zone for POSIXct is UTC, R usually thinks my dates/times are already in UTC, when I know they’re in PST (as much as I would love for R to see my column label of “PST” and magically know what the correct time zone is, it doesn’t work like that). So before I can actually convert the times, I first have to make R aware of the time zone I’m starting in. For this, you can try this base method, or you can use force_tz():

d$Start_DatePST <= force_tz(d$Start_DatePST, tzone="Pacific/Pitcairn")
## [1] TRUE TRUE TRUE


To double-check that your timezone was successfully applied, use:

attributes(d$Start_DatePST)
## $tzone
## [1] "UTC"
## 
## $class
## [1] "POSIXct" "POSIXt"


Now, add a new column for Start_DateUTC, using with_tz() from the lubridate package:

d$Start_DateUTC <- with_tz(d$Start_DatePST, tzone="UTC")
d
##       Location       Start_DatePST       Start_DateUTC
## 1 wallace_weir 2013-09-23 11:19:00 2013-09-23 11:19:00
## 2 wallace_weir 2014-03-18 09:56:00 2014-03-18 09:56:00
## 3 wallace_weir 2014-08-28 09:25:00 2014-08-28 09:25:00


E voila! Calculations are done for you. Hope this is helpful.