4

Yet another date/time related question ;-)

Before you aim and shoot

Things are kind of messed up with a Germany + MS Windows + R combination as the following yields an invalid time zone:

> Sys.timezone()
[1] "MST"
Warning message:
In as.POSIXlt.POSIXct(Sys.time()) : unknown timezone 'MET-1MST'

That's definitely not R's fault, it's Windows. Hence the question in the first place ;-)

Question

Is there an easy/alternative and OS-independent way to query your current country via locale info and then look up the corresponding time zone (format "<country>/<city>", e.g. "Europe/Berlin" for Germany)?

I should also add that I'd like the solution to be independent from internet resources such as stated in this post/answer.

The problem context

Suppose you don't know how to specify your time zone yet. You might have heard something about CET/CEST etc, but AFAIK that doesn't really get you anywhere when using base R functionality (at least being located in Germany ;-)).

You can get a list of available "<country>/<city>" pairs from the /share/zoneinfo/zone.tab file in your RHOME directory. Yet, in order to find the time zone corresponding to the current country you're in you need to know the ISO country code.

Of course we usually do for our native country, but let's suppose we don't (I'd like to end up with a generic approach). What do you do next?

Below is my "four-step" solution, but I'm not really happy with it because

  1. it relies on yet another contrib package (ISOcodes)
  2. I can't test if it works for other locales as I don't know what the info actually would look like if you're in India, Russia, Australia etc.

Anyone got a better idea? Also, It'd be great if some of you in countries other than Germany could run this through and post their locale info Sys.getlocale().

Step 1: get locale info

loc <- strsplit(unlist(strsplit(Sys.getlocale(), split=";")), split="=")
foo <- function(x) {
    out <- list(x[2])
    names(out) <- x[1]
    out
}
loc <- sapply(loc, foo)

> loc
$LC_COLLATE
[1] "German_Germany.1252"

$LC_CTYPE
[1] "German_Germany.1252"

$LC_MONETARY
[1] "German_Germany.1252"

$LC_NUMERIC
[1] "C"

$LC_TIME
[1] "German_Germany.1252"

Step 2: get country name from locale info

country.this <- unlist(strsplit(loc$LC_TIME, split="_|\\."))[2]

> country.this 
[1] "Germany"

Step 3: get ISO country code

Use country.this to look up the associated country code in data set ISO_3166_1 of package ISOcodes

require("ISOcodes")
data("ISO_3166_1")
iso  <- ISO_3166_1
idx  <- which(iso$Name %in% country.this)
code <- iso[idx, "Alpha_2"]

> code
[1] "DE"

Step 4: get time zone

Use code to look up the time zone in the data frame that can be derived from file RHOME/share/zoneinfo/zone.tab

path <- file.path(Sys.getenv("R_HOME"), "share/zoneinfo/zone.tab")    
tzones <- read.delim(
    path, 
    row.names=NULL, 
    header=FALSE,
    col.names=c("country", "coords", "name", "comments"),
    as.is=TRUE, 
    fill=TRUE, 
    comment.char = "#"
)

> tzones[which(tzones$country == code), "name"]
[4] "Europe/Berlin"
Community
  • 1
  • 1
Rappster
  • 12,762
  • 7
  • 71
  • 120
  • without being on windows. what about a `system` call involving the cmd line call mentioned [here](http://www.windows-commandline.com/2010/09/find-time-zone-command-line.html) – Jase_ Jul 05 '12 at 15:50
  • > shell("systeminfo | findstr /C:”Time Zone”") FINDSTR: Zone" kann nicht ge”ffnet werden. Warning message: In shell("systeminfo | findstr /C:”Time Zone”") : 'systeminfo | findstr /C:”Time Zone”' execution failed with error code 1 – Rappster Jul 05 '12 at 15:52
  • 'FINDSTR Zone" kann nicht ge"ffnet werden' translates to 'FINDSTR ZONE" can not be opened' – Rappster Jul 05 '12 at 15:53
  • sorry I'm not on windows so I couldn't test it. I thought it might have done the trick. I have been burnt in the past with time zones+R+windows and generally set the time zone manually. This of course doesn't answer your question. – Jase_ Jul 05 '12 at 15:58
  • That's totally fine, thanks for trying! – Rappster Jul 05 '12 at 16:00
  • @Rappster: try `shell('systeminfo | findstr ".*zone:"')` instead. Or maybe you could use the registry: `readRegistry("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones", "HLM", 2)` (both solutions work only on windows) – sgibb Jul 05 '12 at 17:59
  • @sgibb: thanks for that one. Just tried it, but I still get an error (Win XP, 32 Bit, SP 3): Zeitzone: Nicht verf�gbar (translates to "time zone: not available") – Rappster Jul 05 '12 at 18:48

2 Answers2

2

Specifically regarding your question:

Is there an easy/alternative and OS-independent way to query your current country via locale info and then look up the corresponding time zone?

No - there is not. This is because there are several countries that have multiple time zones. One cannot know the time zone from just the country alone.

This is why TZDB identifiers are in the form of Area/Location, rather than just a list of country codes.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Thanks for clarifying that, makes perfect sense. Then the question would probably rather be how to find out where the IP-address of the computer connecting to the internet is "located" in order to get `area/location`-type information. I know there are web services for that, but do you know of any R package that accomplishes that? – Rappster Jun 10 '13 at 14:50
  • You should read [this](http://stackoverflow.com/q/16086962/634824) to know how to get a time zone. But obtaining a lat/lon from the IP address is called "IP geolocation", and that isn't very reliable since your IP address might be a proxy server. If you have a real address, there are various services that can convert that to coordinates. If you have a mobile device, you can use the GPS or cell-tower location. But there is no one single generic solution unfortunately. – Matt Johnson-Pint Jun 10 '13 at 16:30
0

Some simplifications to your workflow.

You can retrieve just the time part of the locale using

Sys.getlocale("LC_TIME")

which avoids the neeed to split strings.

The lubridate package contains a function to retrieve Olson-style time zone names, so you don't have to worry about reading and parsing zone.tab.

library(lubridate)
olson_time_zones()
Richie Cotton
  • 118,240
  • 47
  • 247
  • 360