Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert between local and universal time using boost::date_time?

How can I convert between local and UTC time (in particular, from local to UTC) using boost::date_time using a current system timezone? I know about boost::date_time::local_adjustor, but it requires a template argument which is a timezone-dependent offset.

Failing platform-independent way to do that, how would I do it specifically on Linux?

As an aside, how are non-existent time points handled during the conversion? For example if a day is one hour short due to DST, and I try to convert a time point from the missing hour, what will be the resultant universal time?

like image 547
Alex B Avatar asked Feb 19 '10 05:02

Alex B


3 Answers

I'm using following code to find difference between local and UTC time:


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

    time_duration UTC_Diff;
    {
        ptime someUTC_Time(date(2008, Jan, 1), time_duration(0, 0, 0, 0));
        ptime someLocalTime = boost::date_time::c_local_adjustor::utc_to_local(someUTC_Time);
        UTC_Diff = someLocalTime - someUTC_Time;
    }

Since you find the difference is't easy to calcutate UTC time.

like image 180
Dmitriy Avatar answered Nov 19 '22 00:11

Dmitriy


If you have a local_date_time in correct timezone, you can directly use utc_time method to get time in UTC.

Looks look you have some plain ptime, which you want to interpret as being in a given timezone and then convert it to UTC for that, I am using this constructor

local_date_time(...)
  Parameters:
    date
    time_duration 
    time_zone_ptr
    bool

According to docs it reinterprets given time data to be in given timezone, it means it can be used to localize any given ptime, and after that utc_time method can be used, here is a utility function to convert any ptime from a given timezone to UTC

ptime get_local_to_utc(const ptime& t, const time_zone_ptr& localtz){
    if(t.is_not_a_date_time()) return t;
    local_date_time lt(t.date(), t.time_of_day(), localtz, local_date_time::NOT_DATE_TIME_ON_ERROR);
    return lt.utc_time();
}
like image 33
Anurag Uniyal Avatar answered Nov 18 '22 23:11

Anurag Uniyal


Converting between UTC and local based on a diff between some chosen time and UTC only works as long as you stay on the same side of the DST change moment.

The following will work for any date (sorry it's not local->UTC):

    bpt::ptime utils::utcToLocal(bpt::ptime utcTime)
{
  // NOTE: the conversion functions between ptime and time_t/tm are broken so we do it ourselves.
  bpt::time_duration timeSinceEpoch = utcTime - bpt::ptime(boost::gregorian::date(1970, 1, 1), bpt::time_duration(0,0,0));
  time_t secondsSinceEpoch = timeSinceEpoch.total_seconds();
  tm* localAsTm = localtime(&secondsSinceEpoch);
  return bpt::ptime(
    boost::gregorian::date(
      localAsTm->tm_year + 1900, 
      localAsTm->tm_mon + 1, 
      localAsTm->tm_mday), 
    bpt::time_duration(
      localAsTm->tm_hour,
      localAsTm->tm_min,
      localAsTm->tm_sec));
}
like image 4
rogierschouten Avatar answered Nov 18 '22 22:11

rogierschouten