5

I am storing messages in UTC. Therefore, if someone looks back to a previous message, I need to be able to convert the timestamp to what the time was relative to what the timezone was then. How do I get what the timezone was then?

For example, on September 3, 2012 the timezone is PDT. The current time offset is -0700. I send a message at 9:06. The time UTC is 16:06.

I come back to this message December 1, 2012. The current timezone is PST. The current time offset is -0800. I look at the message I sent on September 3, 2012. If I were to convert back from UTC using the current time offset I get 8:06 which is NOT when the message was sent. It was sent at 9:06.

Therefore, I need a way to find out that on September 3, 2012 the timezone was PDT, not PST.

P.S. without libraries would be the best, thanks.

chacham15
  • 13,719
  • 26
  • 104
  • 207
  • 1
    Your question confuses me. A time zone is not for a specific period of time (e.g. the time the message was posted), it is for a specific area (e.g. middle europe). –  Sep 03 '12 at 16:03
  • @delnan timezones are not only for specific areas they are also for specific times of the year. That is the difference between PST and PDT. – chacham15 Sep 03 '12 at 16:04
  • That's why I considered adding a "(generally)" in there. Yes, the date can affect the time zone offset, but that does not make your wording any less confusing. The location is still vital. –  Sep 03 '12 at 16:05
  • @delnan I gave an example, does that clear it up? – chacham15 Sep 03 '12 at 16:10
  • A note that you *know* the location, and hence the choice of time zone only depends on daylight saving time et al would have been sufficient. I took the liberty to expand the title, as I fear this omission could already scare off readers. But yes, this is clearer. +1 –  Sep 03 '12 at 16:13

3 Answers3

3

Boost Date_time does that, here is simply example I had hanging around (code below):

edd@max:~/src/progs/C++$ g++ -o boost_posix_time_dst boost_posix_time_dst.cpp
edd@max:~/src/progs/C++$ ./boost_posix_time_dst 
DST ran from 2012-Mar-11 02:00:00 to 2012-Nov-04 02:00:00
DST shortcut PDT
DST name     Pacific Daylight Time
edd@max:~/src/progs/C++$ 

There is also functionality to form a date (your Dec 1, 2012) and see if it is inside a give interval (as formed here by the DST start and end).

I think you can also get it by forming a date and checking the isDST() boolean.

My short program is below. You need a local copy of the csv file which is a) in the Boost sources and b) on a number of sites dealing with timezones (eg Google's first or second hit finds it at CERN):

#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>  
#include <boost/date_time/local_time/local_time.hpp>     

using namespace boost::posix_time;
using namespace boost::gregorian;

int main(int argc, char **argv) {

  boost::local_time::tz_database tz;
  tz.load_from_file("/tmp/date_time_zonespec.csv");

  boost::local_time::time_zone_ptr tzp =
            tz.time_zone_from_region("America/Los_Angeles");    

  int year = 2012;
  boost::posix_time::ptime t1 = tzp->dst_local_start_time(year);
  boost::posix_time::ptime t2 = tzp->dst_local_end_time(year);
  std::cout << "DST ran from " << t1 << " to " << t2 << std::endl;
  std::cout << "DST shortcut " << tzp->dst_zone_abbrev() << std::endl;
  std::cout << "DST name     " << tzp->dst_zone_name() << std::endl;

}
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Can you get the timezone shortcut which is NOT the current timezone (i.e. get PST if you're in PDT and vice versa)? Aside from that this is perfect with the sole exception that I now have to link an entire library for 1 function :(. – chacham15 Sep 03 '12 at 16:33
  • Yes, It will return 'PST' and 'PDT' when you call, respectively, the 'zone' and 'dst' abbrev.name functions. Not that I did _not_ supply a date, just a year! See the boost docs, it is a pretty rich API. – Dirk Eddelbuettel Sep 03 '12 at 16:35
  • +1 Thanks, if an answer without Boost doesnt show up, ill accept yours a bit later. – chacham15 Sep 03 '12 at 16:39
3

If it's a simple C++ application that doesn't require the use of separate time-zones during execution then you can simply use localtime to get a shared struct tm * reference that contains timezone information for a particular time_t that it is called with. If you system is configured with a timezone of PST, then when you invoke localtime, then it will use the pacific timezone information for the display - an example using Jan 1, 2012 (GMT) and June 1, 2012:

time_t def_time = 1325376000;
struct tm *a_tim = localtime(&def_time);
printf("%s %ld %d\n", a_tim->tm_zone, a_tim->tm_gmtoff, a_tim->tm_isdst);
def_time = 1338505200;
a_tim = localtime(&def_time);
printf("%s %ld %d\n", a_tim->tm_zone, a_tim->tm_gmtoff, a_tim->tm_isdst);

On my system (TZ=Europe/Dublin) this displays:

GMT 0 0
IST 3600 1

By overriding the TZ environment variable with America/Los_Angeles I get:

PST -28800 0
PDT -25200 1

i.e. the system is well able to determine the timezone name, offset from GMT and if summer time is in effect from the UTC timestamp.

Edit: trying to use multiple timezones within C/C++ programs simultaneously using the posix supplied timezone routines is horrible, and I would definitely recommend using boost if you're in that situation as it's a quick solution.

Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
  • this is exactly what I wanted. The program doesnt ever need to convert to non local timezones so this is perfect. +1. Just tried to implement it, unfortunately, my system doesnt have the tm_zone member of the tm struct. :( – chacham15 Sep 03 '12 at 17:29
  • 2
    the tm_zone item is a glibc extension (i.e. it's in most linux implementations). You never mentioned the platform in the original request. You can still use the tm_isdst item to determine if it's daylight savings time or not. – Anya Shenanigans Sep 04 '12 at 09:11
0

Just knowing the current offset isn't enough to tell you the offset for the same location at another time of year; there are plenty of pairs of locations that share a timezone for only part of the year (e.g. Central Europe and Algeria, or the eastern US and Colombia).

The simplest fix would be to store the timezone along with the message.

ecatmur
  • 152,476
  • 27
  • 293
  • 366