7

私は多くの例を見てきましたが、この単純なケースに対処しているようです。解析したい文字列は次のとおりです。

「2012-06-0116:45:34EDT」

私は次のように作成しようとしましたlocal_time_input_facet"%Y-%m-%d %H:%M:%S %Z"

local_date_timeオブジェクトのゾーンポインタは常に設定されていません。ドキュメントを読むことは混乱を招きます:

%Z *!フルタイムゾーン名(出力のみ)。ptimeでtime_facetを使用する場合、このフラグは無視されます。

"EDT"//東部夏時間

誰かがこれを以前にやったことがありますか?

更新:問題をもう少しよく説明するためにコードを更新しました:

using namespace std;
using namespace boost::local_time;

int main()
{
    stringstream ss;

    // Set up the input datetime format.
    local_time_input_facet *input_facet 
    = new local_time_input_facet("%Y-%m-%d %H:%M:%S %ZP");
    ss.imbue(std::locale(ss.getloc(), input_facet));

    local_date_time ldt(not_a_date_time),ldt1(not_a_date_time);

    // Read a time into ldt
    ss.str("2012-06-01 17:45:34 EDT");
    ss >> ldt;

    ss.str("2012-06-01 17:45:34 CDT");
        ss >> ldt1;
        std::cerr << (ldt - ldt1).total_seconds() << std::endl;

    // Write the time to stdout.
    cout << "Full Time:\t"   << ldt.to_string() << endl;
    cout << "Local time:\t"  << ldt.local_time() << endl;
    cout << "Time zone:\t"   << ldt.zone_as_posix_string() << endl;
    cout << "Zone abbrev:\t" << ldt.zone_abbrev() << endl;
    cout << "Zone offset:\t" << ldt.zone_abbrev(true) << endl;

    cout << "Full Time:\t"   << ldt1.to_string() << endl;
    cout << "Local time:\t"  << ldt1.local_time() << endl;
    cout << "Time zone:\t"   << ldt1.zone_as_posix_string() << endl;
    cout << "Zone abbrev:\t" << ldt1.zone_abbrev() << endl;
    cout << "Zone offset:\t" << ldt1.zone_abbrev(true) << endl;

    return 0;
}

出力:

0
Full Time:  2012-Jun-01 17:45:34 EDT
Local time: 2012-Jun-01 17:45:34
Time zone:  EDT+00
Zone abbrev:    EDT
Zone offset:    +0000
Full Time:  2012-Jun-01 17:45:34 CDT
Local time: 2012-Jun-01 17:45:34
Time zone:  CDT+00
Zone abbrev:    CDT
Zone offset:    +0000
4

1 に答える 1

7

不具合

ここのブーストのドキュメントによると:http ://www.boost.org/doc/libs/1_57_0/doc/html/date_time/date_time_io.html#date_time.format_flags

%Zは:

フルタイムゾーン名(出力のみ)。

それはまた言う%ZP

Posixタイムゾーン文字列(入力と出力の両方で使用可能)。

%Zしたがって、に変更する必要があります%ZP。これで、タイムスタンプが解析されます。ただし、ゾーンオフセットは設定されないことに注意してください。

Posixタイムゾーン文字列

Posixタイムゾーン文字列の場合、少なくともゾーンの省略形とUTCからのオフセットを指定する必要がありますEST-5

完全なPosixタイムゾーン文字列は次のようにフォーマットされます。

"std offset dst [offset],start[/time],end[/time]"

http://www.boost.org/doc/libs/1_57_0/doc/html/date_time/local_time.html#date_time.local_time.posix_time_zoneによると、スペースなし

ESTおよびPSTの完全なPosixタイムゾーン文字列の例を次に示します。

EST-5EDT,M3.2.0,M11.1.0
PST-8PDT,M4.1.0,M10.1.0

これには、夏時間が有効になる時期に関する情報が含まれています。

ただし、EDT-4何をしているのかによっては、ケースを回避できる場合があります。

Posixタイムゾーンは単純ですが、タイムゾーンルールの履歴の変更を考慮していないという点で制限されていることに注意してください。そもそもタイムゾーンでの作業は避けるのが最善だと思います。

入力フォーマットを制御できない場合はどうなりますか?

OPがコメントで指摘したように、オフセットは彼の入力タイムスタンプにリストされていません。1つの解決策は、入力タイムスタンプの末尾からゾーンの省略形を読み取り(たとえば"EDT")、既知のゾーンの省略形のマップと照合することです。

std::map<std::string, std::string> zone_map;
zone_map["EST"] = "EST-5EDT,M4.1.0,M10.5.0";  // Eastern Standard Time
zone_map["EDT"] = zone_map["EST"];            // Eastern Daylight Time
zone_map["PST"] = "PST-8PDT,M4.1.0,M10.1.0";  // Pacific Standard Time
zone_map["PDT"] = zone_map["PST"];            // Pacific Daylight Time
// ...

(上記のDSTゾーンは、標準のタイムゾーンと同じである必要があることに注意してください。)

また、単純なUTCオフセットを保存するだけでうまくいくかもしれません。

zone_map["EST"] = "EST-5";  // Eastern Standard Time
zone_map["EDT"] = "EDT-4";  // Eastern Daylight Time
// ...

実例

組み込みのタイムゾーンデータベースを使用する例を次に示します。

#include <map>
#include <string>
#include <sstream>
#include <iostream>
#include <boost/date_time/local_time/local_time.hpp>

using namespace boost::local_time;

int main()
{
    // A little database of time zones.
    std::map<std::string, std::string> zone_map;
    zone_map["EST"] = "EST-5EDT,M4.1.0,M10.5.0";  // Eastern Standard Time
    zone_map["EDT"] = zone_map["EST"];            // Eastern Daylight Time
    zone_map["PST"] = "PST-8PDT,M4.1.0,M10.1.0";  // Pacific Standard Time
    zone_map["PDT"] = zone_map["PST"];            // Pacific Daylight Time
    // ...

    // This is our input timestamp.
    std::string timestamp = "2012-06-01 16:45:34 EDT";

    // Replace time zone abbrev with full Posix time zone.
    const size_t abbrev_pos = timestamp.find_last_of(' ') + 1;
    const std::string abbrev = timestamp.substr(abbrev_pos);
    timestamp.replace(abbrev_pos, std::string::npos, zone_map[abbrev]);

    std::cout << "Time stamp with full timezone: " << timestamp << std::endl;

    // Set up the input datetime format.
    local_time_input_facet *input_facet = new local_time_input_facet("%Y-%m-%d %H:%M:%S %ZP");
    std::stringstream ss;
    ss.imbue(std::locale(ss.getloc(), input_facet));

    // This is our output date time.
    local_date_time ldt(not_a_date_time);

    // Read the timestamp into ldt.
    ss.str(timestamp);
    ss >> ldt;

    // Write the time to stdout.
    std::cout << "Full Time:\t"   << ldt.to_string() << std::endl
              << "Local time:\t"  << ldt.local_time() << std::endl
              << "Time zone:\t"   << ldt.zone_as_posix_string() << std::endl
              << "Zone abbrev:\t" << ldt.zone_abbrev() << std::endl
              << "Zone offset:\t" << ldt.zone_abbrev(true) << std::endl;

    return 0;
}

これは以下を出力します:

Time stamp with full timezone: 2012-06-01 16:45:34 EST-5EDT,M4.1.0,M10.5.0
Full Time:      2012-Jun-01 16:45:34 EDT
Local time:     2012-Jun-01 16:45:34
Time zone:      EST-05EDT+01,M4.1.0/02:00,M10.5.0/02:00
Zone abbrev:    EDT
Zone offset:    -0400

ここでの解決策は理想的ではないかもしれませんが、それが私がそれを行うために見ることができる唯一の方法です。

于 2012-06-04T00:13:51.303 に答える