可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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.
回答1:
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; }
回答2:
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.
回答3:
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.