10

The problems is:

  • I know how to get the local time in boost

the code:

    boost::local_time::local_date_time currentTime(
        boost::posix_time::second_clock::local_time(),
        boost::local_time::time_zone_ptr());
    std::cout << currentTime.local_time() << std::endl;
  • I know how to get the current time zone data from the machine (I hope it's a right way)

the code:

tzset();
// the var tzname will have time zone names
// the var timezone will have the current offset
// the var daylight should show me if there is daylight "on"

but still I can't get local_date_time with the current time_zone... Does someone know, how to do it?

Alek86
  • 1,489
  • 3
  • 17
  • 26
  • Do you *have* to print the time in localtime? If you're able to use UTC you'll save yourself all sorts of headaches. – Mark B Jan 05 '12 at 17:34
  • Take a look at the [Date Time IO Tutorial](http://www.boost.org/doc/libs/1_48_0/doc/html/date_time/date_time_io.html#date_time.io_tutorial)? – Georg Fritzsche Jan 05 '12 at 17:56
  • "Do you have to print the time in localtime?" Yes, I have to :( – Alek86 Jan 05 '12 at 17:59
  • 1
    "Take a look at the Date Time IO Tutorial?" I presume you have found the answer there? If yes, I would be happy if you show me it in this tutorial, because I tried to find it on boost.org (and not only) for 2 days – Alek86 Jan 05 '12 at 18:01
  • Looks like one of the default time facets might do it or alternatively a custom one with the `%Q` formatter. Or do i misread the question? – Georg Fritzsche Jan 05 '12 at 18:29
  • 1
    :Or do i misread the question?" Looks like I wrote it badly... I do know how to print the local_date_time, I don't know how to get local_date_time with the current date-time and time zone – Alek86 Jan 05 '12 at 18:33
  • The var daylight only shows you if daylight _could be on_, NOT if it is on right now. – AmokHuginnsson Nov 07 '12 at 16:07

3 Answers3

2

OK, as for now I still don't know the whole answer

but there is code, which could help to print the current time zone offset

(based on an answer for a related question here (stackoverflow) and some inner boost code)

I'm absolutely not sure it's will work correctly on all machines, but for now it's better than nothing:

boost::posix_time::time_duration getUtcOffset(const boost::posix_time::ptime& utcTime)
{
    using boost::posix_time::ptime;
    const ptime localTime = boost::date_time::c_local_adjustor<ptime>::utc_to_local(utcTime);
    return localTime - utcTime;
}

std::wstring getUtcOffsetString(const boost::posix_time::ptime& utcTime)
{
    const boost::posix_time::time_duration td = getUtcOffset(utcTime);
    const wchar_t fillChar = L'0';
    const wchar_t timeSeparator = L':';

    std::wostringstream out;
    out << (td.is_negative() ? L'-' : L'+');
    out << std::setw(2) << std::setfill(fillChar)
        << boost::date_time::absolute_value(td.hours());
    out << L':';
    out << std::setw(2) << std::setfill(fillChar)
        << boost::date_time::absolute_value(td.minutes());
    return out.str();
}
int main()
{
    const boost::posix_time::ptime utcNow =
        boost::posix_time::second_clock::universal_time();

    const std::wstring curTimeOffset = getUtcOffsetString(utcNow);
    std::wcout << curTimeOffset.c_str() << std::endl;  // prints  -05:00  on my comp 
}
Alek86
  • 1,489
  • 3
  • 17
  • 26
  • Ignoring DST means that calendar arithmetic (e.g., subtract a date_duration) won't work correctly on returned local_date_time object. – Florian Winter Jul 19 '16 at 08:59
  • The asker asked how to get a `local_date_time` object with the current time and time zone offset, but this just prints the offset. Can you adjust your answer please? – Chris Watts Jun 27 '18 at 10:13
0

Since you say you have timezone information the only question is how to use boost for formatting string you need. Below is a sample code:

  using namespace boost::local_time;
  using namespace boost::posix_time;

  // Composing this string is the most tricky part. Syntax see in:
  // boost\date_time\local_time\posix_time_zone.hpp
  string posix_tz_def("PST-5PDT01:00:00,M4.1.0/02:00:00,M10.1.0/02:00:00");
  local_date_time ldt(second_clock::local_time(),
                      time_zone_ptr(new posix_time_zone(posix_tz_def)));

  std::stringstream ss;
  local_time_facet* output_facet = new local_time_facet();
  ss.imbue(std::locale(std::locale::classic(), output_facet));
  output_facet->format("%Y-%m-%dT%H:%M:%S %Q");
  ss << ldt;

  string formatted_datetime = ss.str();  // 2012-01-05T18:14:06 -05:00

In this approach most problematic part is posix timezone string. I think there should be databases with these strings for every timezone and boost provides a template for working with .csv file. If the only thing you need is offset in the string just setup DTS to 0:00:00 and don't care about the rest. For example use this string: PST-5:30PDT0,0,365 (forever PDT, shift 0). Substitute "-5:00" with the offset you need.

Though, C++/boost way would be implementing own timezone provider by deriving from date_time::time_zone_base.

More samples and ideas could be found here.

real4x
  • 1,433
  • 12
  • 11
0

So, if you also need to obtain correct UTC offset than my previous example should be modified a bit to produce correct timezone string:

static boost::posix_time::time_duration utc_offset(
    second_clock::local_time() - second_clock::universal_time());
std::ostringstream ss_posix_tz_def;
// We don't care about real zone name so, just put any three letters.
ss_posix_tz_def << "LOC" << utc_offset;
string posix_tz_def = ss_posix_tz_def.str();

Another solution is writing a whole new timezone provider. Like this simple one:

// We assume local TZ doesn't have DST, UTC offset is calculated basing on
// local system clocks. Thus, using of this provider for time calculations for
// an arbitrary date is not a good idea.
class machine_time_zone : public boost::local_time::custom_time_zone {
 public:
  typedef boost::local_time::custom_time_zone base_type;
  typedef base_type::time_duration_type time_duration_type;

  machine_time_zone()
    : boost::local_time::custom_time_zone(
        time_zone_names("Local machine TZ", "LOC", "", ""),
        GetUTCOffset(),
        boost::local_time::dst_adjustment_offsets(
            time_duration_type(0, 0, 0),
            time_duration_type(0, 0, 0), time_duration_type(0, 0, 0)),
        boost::shared_ptr<boost::local_time::dst_calc_rule>()) {
  }

  // This method is not precise, real offset may be several seconds more or less.
  static const boost::posix_time::time_duration& GetUTCOffset() {
    using boost::posix_time::second_clock;
    static boost::posix_time::time_duration utc_offset(
      second_clock::local_time() - second_clock::universal_time());
    return utc_offset;
  }
};

Just pass it when constructing local_date_time:

local_date_time ldt(second_clock::local_time(),
                    time_zone_ptr(new machine_time_zone()));
real4x
  • 1,433
  • 12
  • 11
  • Ignoring DST means that calendar arithmetic (e.g., subtract a date_duration) won't work correctly on returned local_date_time object. – Florian Winter Jul 19 '16 at 08:59