2016-04-06 12 views
0

私は(Linux上で実行される)クライアント/サーバーカスタムアプリケーションで作業しており、送信するフレームの1つにタイムスタンプ(つまり、フレームが送信される時間)が含まれています。UTCタイムスタンプの比較

私のアプリケーションを信頼できるものにするために、私はgmtimeを使ってクライアントで時刻を生成しました。私はベルギーにいるので、今はクライアントVMの時間が(夏時間のために)UTC時間より2時間遅れています。

サーバー側では、最初に受信した文字列をtime_tタイプに変換します。私はdifftime関数を使用してタイムスタンプが古すぎないかどうかを調べるためにこれを行います。 次に、タイムスタンプ(UTC時刻)をgmtimeで再度生成し、それをtime_tに変換します。

私は時差を見るために2つのtime_tを比較します。

私はサーバー側での時間の変換に問題があります。機能(time_str)のタイムスタンプを生成し、それを文字列にエクスポートする:


クライアント側が...私は、クライアントと同じコードを使用しますが、出力されたgmtimeは異なっている

std::string getTime() 
    { 
    time_t rawtime; 
    struct tm * timeinfo; 
    char buffer[80]; 

    time (&rawtime);    // Get time of the system 
    timeinfo = gmtime(&rawtime); // Convert it to UTC time 

    strftime(buffer,80,"%d-%m-%Y %H:%M:%S",timeinfo); 
    std::string time_str(buffer); // Cast it into a string 
    cout<<"Time Stamp now (client) : "<<time_str<<endl; 

    return time_str; 
    } 

そして、それは(9h33現地時間)、これをproduices:

時間S今タンピング:2016年6月4日7時33分30秒


サーバーサイド: fucntion、タイムスタンプを取得newxタイムスタンプを生成し、それらを比較する:

bool checkTimeStamp(std::string TimsStamp_str, double delay) 
{ 
    cout<<"TimeStamp recieved: "<<TimsStamp_str<<endl; 
    /* Construct tm from string */ 
    struct tm TimeStampRecu; 
    strptime(TimsStamp_str.c_str(), "%d-%m-%Y %I:%M:%S", &TimeStampRecu); 
    time_t t_old = mktime(&TimeStampRecu); 

    /* Generate New TimeStamp */ 
    time_t rawtime; 
    struct tm * timeinfo; 
    time (&rawtime); // Get time of the system 
    timeinfo = gmtime(&rawtime); // convert it to UTC time_t 
    time_t t2 = mktime(timeinfo); // Re-Cast it to timt_t struct 
    /* Convert it into string (for output) */ 
     char buffer[80]; 
     strftime(buffer,80,"%d-%m-%Y %H:%M:%S",timeinfo); 
     std::string time_str(buffer); // Cast it into a string 
     cout<<"Time Stamp now (server) : "<<time_str<<endl; 

    /* Comparison */ 
    double diffSecs = difftime(t2, t_old); 
    cout<<diffSecs<<endl; 
    bool isTimeStampOK; 
    if (diffSecs < delay) 
     isTimeStampOK = true; 
    else 
     isTimeStampOK = false; 

return isTimeStampOK; 
} 

そして、それは、(ベルギー9h33で)これを生成します。受け取っ

タイムスタンプ:2016年6月4日7時33分30秒

タイムスタンプになりました(サーバー):2016年6月4日午前8時33分31秒


はなぜどちらのlocaltime(9h33)で、どちらもUTC時間のサーバー時間(8h33)(あります7h33)?

私は世代を間違えましたか?私は、クライアント側とまったく同じコードなので、どこにあるのかわかりません...

+0

2つのVMがCentOSを実行している現地時間にあることを忘れていました。 – EisenHeim

答えて

4

コードにいくつかのエラーがありますが、いくつかのエラーがあります。ここでの最大の問題は、C <time.h> APIが非常に貧弱で、混乱し、不完全で、エラーが発生しやすく、このようなエラーが非常に厳しいことです。それについては後で詳しく説明します。

最初の問題は、この行である:

struct tm TimeStampRecu; 

それが初期化されていないtmを作成し、strptimeにそれを渡します。 strptimeは、TimeStampRecuのすべての欄に記入しないことがあります。あなたは、このようなTimeStampRecuをゼロに初期化する必要があります。

struct tm TimeStampRecu{}; 

次の問題:

strptime(TimsStamp_str.c_str(), "%d-%m-%Y %I:%M:%S", &TimeStampRecu); 

%Iで示される12時間の時間は、AM/PM指定せずにあいまいです。私はあなたがそれを使用する唯一の場所なので、これはちょうどタイプoと思われます。

次に問題:

gmtime time_t -> tm UTC to UTC 
mktime tm -> time_t local to UTC 

ある、mtkimeは、それが実行されているコンピューターのローカル時間に応じて入力tmを解釈します。あなたが代わりに必要なのです。残念ながら

timegm tm -> time_t UTC to UTC 

timegmは、標準C(またはC++)ではありません。幸いにもそれはあなたのシステムにとにかく存在するでしょう。

これらの変更により、あなたのコードは期待通りに動作すると思います。

ここ

https://github.com/HowardHinnant/date

はあなたのコードが変換されます。


あなたがC++ 11を使用している場合は、ここではこれを行うには、より安全な日付/時刻ライブラリ(フリー/オープンソース)があります

std::string getTime() 
{ 
    using namespace std::chrono; 
    auto rawtime = time_point_cast<seconds>(system_clock::now()); 
    auto time_str = date::format("%d-%m-%Y %H:%M:%S", rawTime); 
    std::cout<<"Time Stamp now (client) : "<<time_str<< '\n'; 

    return time_str; 
} 

bool checkTimeStamp(std::string TimsStamp_str, std::chrono::seconds delay) 
{ 
    using namespace std::chrono; 
    std::cout<<"TimeStamp recieved:  "<<TimsStamp_str<< '\n'; 
    /* Construct tm from string */ 
    std::istringstream in{TimsStamp_str}; 
    time_point<system_clock, seconds> t_old; 
    date::parse(in, "%d-%m-%Y %H:%M:%S", t_old); 

    /* Generate New TimeStamp */ 
    auto rawtime = time_point_cast<seconds>(system_clock::now()); 
    auto time_str = date::format("%d-%m-%Y %H:%M:%S", rawTime); 
    in.str(time_str); 
    time_point<system_clock, seconds> t2; 
    date::parse(in, "%d-%m-%Y %H:%M:%S", t2); 
    cout<<"Time Stamp now (server) : "<<time_str<<endl; 

    /* Comparison */ 
    auto diffSecs = t2 - t_old; 
    cout<<diffSecs.count()<<endl; 
    bool isTimeStampOK; 
    if (diffSecs < delay) 
     isTimeStampOK = true; 
    else 
     isTimeStampOK = false; 

    return isTimeStampOK; 
} 
0

タイムスタンプは絶対値です。タイムゾーンやDSTに依存しません。過去の一定の瞬間からの秒数を表します。 time()によって返される値は、サーバーのタイムゾーンが何であっても同じです。

あなたのコードはタイムスタンプを生成しませんが、人間の消費のためにフォーマットされた日付です。

タイムスタンプを内部的に使用し、UIでのみ人間が読むことのできる日付にフォーマットすることをお勧めします。しかし、アプリケーションのさまざまなコンポーネント間で日付を文字列として渡す必要がある場合は、タイムゾーンもその中に入れます。

私は(唯一のタイムスタンプを使用して)、このようにコードを記述します。

// The client side 
time_t getTime() 
{ 
    return time(NULL); 
} 


// The server side 
bool checkTimeStamp(time_t clientTime, double delay) 
{ 
    time_t now = time(NULL); 

    return difftime(now, clientTime) < delay; 
} 

更新

あなたは、クライアントとサーバー間の通信に文字列を使用する必要がある場合は、あなたがしなければならないすべてがあります(クライアント上の)日付としてタイムスタンプをフォーマットし、(サーバー上の)タイムスタンプに日付を解析して、日付の書式設定に使用したタイムゾーンを含めるために使用する書式文字列を更新します。

これは、%Zをコード内のどこにでもフォーマットに追加することを意味します。 "%d-%m-%Y %H:%M:%S %Z"を使用してください。 Btw、あなたが今投稿したコードはstrptime()への呼び出しで"%d-%m-%Y %I:%M:%S"と読んで、それはあなたに午後に別の問題をもたらします。それは明確なロケールに依存しているので、私はいつも"%Y-%m-%d %H:%M:%S %Z"を使用

備考

06-04-2016は、読者の母国語に応じて、April 6またはJune 4と解釈することができます。

+0

クライアントとサーバーの間で文字列を渡す必要があります。 'time_t'を文字列に変換するには、' localtime'や 'gmtime'で生成される' struct tm'を渡す必要があります。それがエラーの原因です。 – EisenHeim

+0

コードに必要な修正(文字列の使用を続ける)で答えを更新しました。 – axiac

+0

私はあなたの変更を考慮に入れましたが、エラーは残ります...サーバで生成されたタイムスタンプは 'CEST'ですが、**このタイムスタンプに示された時間はCEST時間ではありません... **私はこれを持っています: '2016-04-06 10:00:25 CEST '(11時にCESTで走った時)... – EisenHeim

関連する問題