2016-11-14 3 views
9

任意のUnixタイムスタンプ(秒)に基づいて、カリフォルニア(太平洋標準時)の曜日をどのように決定できますか?私は検索しましたが、C++用の組み込みライブラリは見つかりませんでした。C++でunixのタイムスタンプを曜日に変換しますか?

UTCは一般にPTより8時間遅れていますが、Unixのタイムスタンプから8時間を引いてtm構造体を作成するだけでは、夏時間のニュアンスが割り引かれるため機能しません。

+1

私はあなたにdownvoteをしませんでしたが、['std :: localtime'](http://en.cppreference.com/w/cpp/chrono/c/localtime)はどうですか? – Danh

+1

ありがとうございます - 現地時間が私にとってPTでない場合はどうですか? –

+3

[strftime](http://en.cppreference.com/w/cpp/chrono/c/strftime)。または[time_put](http://en.cppreference.com/w/cpp/locale/time_put)。または[Howard Hinnantの日付](https://github.com/HowardHinnant/date) - 答えではなくポインタなので、これはコメントです。 –

答えて

9

Howard Hinnant's date libraryを使用してこれを行う方法は次のとおりです。これは<chrono>に基づいて無料のC++ 11月14日MITライセンスのライブラリです:

#include "tz.h" 
#include <iostream> 

int 
main() 
{ 
    using namespace std::chrono_literals; 
    using namespace date; 
    auto unix_timestamp = sys_seconds{1479664467s}; 
    auto zt = make_zoned("America/Los_Angeles", unix_timestamp); 
    auto wd = weekday{floor<days>(zt.get_local_time())}; 
    std::cout << wd << '\n'; 
} 

最初の行は、ちょうど(あなたが他のソースから持っている場合があります)Unixタイムスタンプを構築します。 C++ 11では、我々は、クロノリテラルを持っていないので、このラインは、代わりに次のようになります。

auto unix_timestamp = sys_seconds{seconds{1479664467}}; 

make_zoned()unix_timestamptime_zone「アメリカ/ Los_Angeles」に基づいてzoned_time<seconds>を作成します。 zoned_timeは、time_zoneとunixタイムスタンプのコレクションです。

zoned_timeのローカルタイムをzt.get_local_time()で取得できます。これはchrono::time_pointですが、クロックは関連付けられていません。この時点の精度は、元のタイムスタンプの精度(この場合は秒)に等しくなります。

あなたはdaysの精度にlocal_timeを切り捨てることによりlocal_timeの週の局所的な一日を取得することができます:

floor<days>(zt.get_local_time()) 

そして、この日の精度time_pointweekdayを入力して変換します。

weekdayは、計算と比較にweekdayに参加するか、明示的に[0,6]の範囲のunsignedに変換することができます。

出力上記プログラム:

Sun 

このライブラリのタイムゾーンの一部がIANA timezone databaseの忠実な表現です。現地時間帯とUTCとの間の正確な調整は、1800年代中頃から現在までの間にはじめて行われます。 1800年代半ばより前にライブラリタイムスタンプを渡すと、最も早い既知のUTCオフセットが-32768年に逆方向に外挿されます。将来のタイムスタンプを32767年として渡すこともでき、現在のオフセットと夏時間のルールが進展します。

このライブラリは<chrono>上に構築されているため、<chrono>が提供する精度を処理します。 nanosecondsなどの一部のchrono::durationは、より限定された範囲(nanosecondsの場合は+/- 292年)です。

ライブラリ/プロセスはスレッドセーフです。つまり、プログラムは、コンピュータのタイムゾーンまたは環境変数を変更せずに、指定したタイムゾーンで直接動作します。また、非const関数のローカル統計のためにスレッドセーフではないことが知られているCタイミングAPIの部分は含まれていません。

gcc、clang、およびVSの最近のバージョンに移植されています。

標準UNIX C(非スレッドセーフ版)を使用して
1

Boostライブラリを使用できますか? タイムゾーン(PST)のPosixタイムゾーン文字列(IEEE Std 1003.1、http://www.boost.org/doc/libs/1_62_0/doc/html/date_time/local_time.html#date_time.local_time.posix_time_zoneを参照)がわかる場合は、以下の例が役立ちます。

#include <iostream> 
#include <ctime> 
#include <boost/date_time.hpp> 

int main(int argc, char ** argv) 
{ 
    std::string posix_time_zone_string = "EST-05:00:00"; // you need to change this to the posix time representation of your desired timezone 

    time_t unix_time = 1479641855; //1479641855 = Sun, 20 Nov 2016 11:37:35 GMT 

    boost::posix_time::ptime pt = boost::posix_time::from_time_t(unix_time); 
    std::cout << "time in UTC: " << boost::posix_time::to_iso_extended_string(pt) << std::endl; 


    boost::local_time::time_zone_ptr zone(new boost::local_time::posix_time_zone(posix_time_zone_string)); 

    boost::local_time::local_date_time dt_with_zone(pt, zone); 
    std::cout << "time in local timezone: " << boost::posix_time::to_iso_extended_string(dt_with_zone.local_time()) << std::endl; 

    // Get the week day (alternative 1) 
    std::cout << "local week day integer: " << boost::local_time::to_tm(dt_with_zone).tm_wday << std::endl; // 0=sunday, 1=monday, etc. 

    // Get the week day (alternative 2) 
    std::cout << "local week day name: " << dt_with_zone.local_time().date().day_of_week() << std::endl; 
    std::cout << "local week day integer: " << int(dt_with_zone.local_time().date().day_of_week()) << std::endl; 
    return 0; 
} 
2

ハック方法:

#include <stddef.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 

void print_times() { 
    char my_buf[100]; 
    time_t now = time(NULL); 
    printf(ctime(&now)); 
    strftime(my_buf, 100, "DoW=%w Tz=%Z\n", localtime(&now)); 
    printf(my_buf); 
} 

int main(int argc, char * argv[]) { 
    print_times(); 
    setenv("TZ", "America/Los_Angeles", 1); 
    print_times(); 
    unsetenv("TZ"); 
    print_times(); 
} 

残念ながら、TZのenv VARまたは/etc/localtimeあなたはUNIX時間関数のタイムゾーンの設定を行うことができる唯一の方法であるファイルを変更する(アンダーフードtzset()は、これらのソースを使用して、すべてのライブラリ関数のタイムゾーン設定をエンコードする共有変数のセットを初期化します。

UNIXのTZ文字列を必要なゾーンに付ける必要があります。 zoneinfo形式は、使用するのが最も簡単で推奨される形式です。私は、太平洋時間のTZ値を生成するためにtzselectを使用しました。

標準のUNIXタイムゾーン設定については、man 5 localtime,man tzselectも参照してください。

関連する問題