On Aug 23, 2013, at 3:12 AM, Daniel Haugstvedt wrote: > I am replying to my own question in case someone else finds this tread and > needs help with the same problem. Thanks to Mark Leeds for helping me on my > way. Any errors or flaws are mine since I have rewritten most of his comments > to make sure I understood them correctly. > > First three general recommendations for time zone problems: > > 1) When asking time zone related questions always give OS information. It > does not hurt to give information on version etc. either. My system is OSX, > lion (10.8.4). Using str(R.Version()) to get system information is one option. > > str(R.Version()) > List of 14 > $ platform : chr "x86_64-apple-darwin9.8.0" > $ arch : chr "x86_64" > $ os : chr "darwin9.8.0" > $ system : chr "x86_64, darwin 9.8.0" > . > . > . > $ version.string: chr "R version 2.15.1 (2012-06-22)" > $ nickname : chr "Roasted Marshmallows > > 2) Before you do ANYTHING with timezones, put Sys.setenv(TZ = "UTC") in your > .Rprofile ir at the tiop of the code you're working in. Otherwise, if you > start trying to convert date time objects to plain date objects, things can > really get whacked. > > 3) Check that the time zone you are using is valid. > > I am no expert on this, but from what I understand, in OSX a valid time zone > has the name of one of the files in the folder > > /usr/share/zoneinfo, > > with some obvious exceptions like the files "iso3166.tab", "posixrules" and > "zone.tab". It can also be one of the entries in the file, > /usr/share/zoneinfo/zone.tab. > > CET and CEST (daylight savings time) are the time zone my system use when > nothing is specified. I am sorry for writing ETC in one of the lines in the > first email. > > > Now, to the problem: How do I change from POSIXct to numeric and back with > another time zone than UTC? > > I have tried to simplify the original question and attempted and answer. > Please correct me if I am wrong. > > > > > Sys.setenv(TZ = "UTC") > > ## Number of seconds from '1970-01-01 00:00:00 UTC' to '2000-01-30 00:00:00 > CET' not > ## counting leap seconds. Display as CET date > tmp = as.POSIXct( '2000-01-30', origin = '1970-01-01' , tz = "CET") > > ## Number of seconds from '1970-01-01 00:00:00 UTC' to '2000-01-30 00:00:00 > CET' not > ## counting leap seconds. Display as UTC date > tmp2 =as.POSIXct( as.numeric( tmp ),origin = '1970-01-01' , tz = "UTC") > > ## What I wanted was to go to numeric and back to the original with the same > time zone. What I got was > ## the number of seconds from '1970-01-01 00:00:00 UTC' to '2000-01-30 > 00:00:00 UTC' not > ## counting leap seconds. Display as CET date. Which is 60*60 seconds less > then I expect. > tmp3 = as.POSIXct( as.numeric( tmp ),origin = '1970-01-01' , tz = "CET") > > ## Solution: Convert to the desired time zone after as.POSIXct has been used > wit UTC to get the > ## correct number of seconds > tmp4 = tmp2 > attributes(tmp4)$tzone = 'CET' > > > tmp > [1] "2000-01-30 CET" >> tmp2 > [1] "2000-01-29 23:00:00 UTC" >> tmp3 > [1] "2000-01-29 23:00:00 CET" >> tmp4 > [1] "2000-01-30 CET" >> >> as.numeric(tmp) > [1] 949186800 >> as.numeric(tmp2) > [1] 949186800 >> as.numeric(tmp3) > [1] 949183200 >> as.numeric(tmp4) > [1] 949186800 > > > My conclusions are > 1) The tz argument sets the tzone attribute but it also determines how the > entered date should be interpreted IF the date is entered as a string. > 2) If the date is entered as numeric it is assumed to be the number of > seconds from UTC to UTC and the tz argument is used to add / subtract the > number of seconds which converts it to the time zone specified.
Thank you for this discussion (and I share your pain.) You might want to look at the various `as.POSIXct` methods with: methods(as.POSIXct) I see 10 methods on my machine at the moment, but some are from the zoo package, so you may see a different number. You are describing differences in how `as.POSIXct.numeric` behaves versus `as.POSIXct.default` which I believe is where a character or factor argument ends up after first being passed through `as.POSIXlt`. In other parts of your question the behavior of `as.POSIXct.Date`, `as.POSIXct.dates`, and `as.POSIXct.default` are illustrated. I have had similar difficulties understanding TZ behavior. It would be nice if R automagically looked up the current setting of my system timeszone. > > Some additional conclusions that I came across while testing a bit. The code > which made me draw them are attached at the end. > 3) If a time zone is not needed the tz argument does nothing. It sets the > tzone but it does not change it. > 4) The origin is assumed to be UTC regardless of what Sys.timezone() say as > long as no time zone for the origin is specified. I checked this by changing > the Sys.timezone() to CET before running the example again. My understanding: All items in a vector need to be in the same TZ. You cannot mix the TZ argument within a vector. Hence, it may be better to always convert to UTC for storage (and for mental clarity) and only use TZ's for the format.POSIXt output. I am not able to figure out where the canonical translation for TZ abbreviations lies on my MacOS 10.8.5 machine. The file at: ?timezone Using the example code with: tzfile <- "/usr/share/zoneinfo/zone.tab" ... does not have any three letter abbreviations. My value for TZ is numbered 390, with a name of "America/Los_Angeles". My Sys.time function behaves properly: > Sys.time() [1] "2013-08-23 09:54:58 PDT" But: "How do it know?" If I change my system TZ to US Central Daylight time there is no apparent recognition of that fact in the output of Sys.time() ... I think I may need to change a locale variable. If I enter a TZ with Sys.setenv() I get CDT as the output: > Sys.setenv(TZ = "America/Chicago") > Sys.time() [1] "2013-08-23 12:00:11 CDT" So I can change R's understanding of the local TZ if I use the full tzone$name value but offering a value of either PDT or PST will fail for the Sys.setenv(TZ=) argument. (Sys.getenv('TZ') returns "" when I start R.) Best of luck in this quest and thanks for the illuminating exercises. (And I thought your spelling was as good as most native English speakers, certainly better than I generally exhibit, so I think you shoudl stop apologizing.) -- David. > > Best regards > > Daniel Haugstvedt > Ph.d student > NTNU, Trondheim, Norway > > > ## If a time zone is not needed the tz argument does nothing. It sets the > tzone but it does not change it. > Sys.setenv(TZ = "UTC") > tmp = as.POSIXct( '2000-01-30', origin = '1970-01-01' , tz = "CET") > tmp2 = as.POSIXct(tmp, tz = "CET") > >> tmp > [1] "2000-01-30 CET" >> tmp2 > [1] "2000-01-30 CET" > > > ## Sys.setenv does not change the time zone of the origin > Sys.setenv(TZ = "CET") > > tmp5 = as.POSIXct( '2000-01-30', origin = '1970-01-01' , tz = "CET") > tmp6 =as.POSIXct( as.numeric( tmp5 ),origin = '1970-01-01' , tz = "UTC") > tmp7 = as.POSIXct( as.numeric( tmp5 ),origin = '1970-01-01' , tz = "CET") > > tmp5 > [1] "2000-01-30 CET" >> tmp6 > [1] "2000-01-29 23:00:00 UTC" >> tmp7 > [1] "2000-01-29 23:00:00 CET" >> >> as.numeric(tmp5) > [1] 949186800 >> as.numeric(tmp6) > [1] 949186800 >> as.numeric(tmp7) > [1] 949183200 > > > > On 22 Aug 2013, at 15:22, Daniel Haugstvedt <daniel.haugstv...@gmail.com> > wrote: > >> From POSIXct to numeric and back with time zone >> >> I am running regressions on data which has time series with different time >> resolution. Some data has hourly resolution, while most has either daily or >> weekly resolution. Aggregation is used to make the hourly data daily, while >> liner interpolation is used to find daily data from the weekly time series. >> This data manipulation requires some careful handling of date and time. >> >> I do travel across time zones and want my code to keep working as the system >> time zone changes. >> >> So far quick fixes have been used to handle problems. Now I am trying to get >> a grip and make a more robust solution. Google and forums have left me with >> an increasing amount of questions instead of answers. >> >> I have chosen one question and one problem. The question, which should be >> trivial, should allow me to solve the problem. However, I have been stuck >> with this all day so if anyone know the solution to the problem straight >> away, it will be highly appreciated. >> >> >> The question: What does the tz attribute in POSIXct do? >> >> >> >> As an example, two dates with different time zone attributes, tmp1 and tmp2, >> are compared. >> >> >>> tmp1 = as.POSIXct('2000-01-30',origin = '1970-01-01', tz = "UTC") >> >>> tmp1 >> >> [1] "2000-01-30 UTC" >> >> >>> tmp2 = as.POSIXct('2000-01-30',origin = '1970-01-01', tz = "ETC") >> >>> tmp2 >> >> [1] "2000-01-30 UTC" >> >> >> The time displayed, including the time zone, is the same but the tzone >> attributes are not. >> >> >>> attributes(tmp1) >> >> $class >> >> [1] "POSIXct" "POSIXt" >> >> >> $tzone >> >> [1] "UTC" >> >> >> >>> attributes(tmp2) >> >> $class >> >> [1] "POSIXct" "POSIXt" >> >> >> $tzone >> >> [1] "ETC" >> >> >> As a final check the numbers are compared >> >> >>> as.numeric(tmp1) >> >> [1] 949190400 >> >>> as.numeric(tmp2) >> >> [1] 949190400 >> >> >> and they match. >> >> >> I was under the impression that POSIXct always used UTC and that the tzone >> attribute was only for displaying and converting to POSIXlt but that seems >> wrong in the above example. As far as I can see, the tzone attribute is >> neither used for display, as both dates display as UTC, and not used to >> change to origin, as both numbers are the same. My question is, what does >> the tzone attribute in POSIXct actually do? >> >> >> I hope increased understanding of that part will let me solve the true >> problem without further assistance. >> >> >> >> >> The problem: from POSIXct to numeric and back. >> >> >>> tmp3 = as.POSIXct( '2000-01-30', origin = '1970-01-01' ) >> >> tmp3 >> >> [1] "2000-01-30 CET" >> >> >> Converting it to numeric and back to POSIXct it becomes >> >>> as.POSIXct( as.numeric( tmp3 ),origin = '1970-01-01' ) >> >> [1] "2000-01-29 23:00:00 CET" >> >> >> which is "2000-01-30 UTC". By converting to numeric and back to POSIXct, an >> hour has been added. This is not the behavior I want. I am trying to sett >> the tz attribute but it does not change the added hour. >> >> >> Trying to understand more of what is going on and to replicate the original >> date, I set the time zone to be CET in both conversions. >> >> >> as.POSIXct( as.numeric( as.POSIXct( '2000-01-30', origin = '1970-01-01', tz >> = "CET" ) ), origin = '1970-01-01', tz = "CET" ) >> >> [1] "2000-01-29 23:00:00 CET" >> >> >> Which is "2000-01-30 UTC". Choosing set the time zone to be UTC in both >> conversions, >> >> >> as.POSIXct( as.numeric( as.POSIXct( '2000-01-30', origin = '1970-01-01', tz >> = "UTC" ) ), >> origin = '1970-01-01', tz = "UTC" ) >> >> [1] "2000-01-30 UTC", >> >> >> I want to convert the date "2000-01-30 CET" to POSIXct and then over to >> numeric before finally converting back to POSIXct without changing the date, >> time or time zone. I seem to get "2000-01-30 UTC" regardless of what I try >> so I am definitely missing something obvious. >> >> >> Best Regards >> >> >> Daniel Haugstvedt >> >> Ph.d.-student, >> >> NTNU, Trondheim, Norway >> >> >> PS. I am aware that my spelling is poor. Any comments on how it could be >> improved are appreciated but send it to me personally and not the list. > -- David Winsemius Alameda, CA, USA ______________________________________________ R-help@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide http://www.R-project.org/posting-guide.html and provide commented, minimal, self-contained, reproducible code.