質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

5回答

1050閲覧

自作日付構造体の差分の取り方

JanTh1989

総合スコア87

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2019/09/26 11:29

編集2019/09/26 11:59

バイナリファイルから年からミリ秒にかけての日時データ(time_t構造体などのような)を取って、ミリ秒差分を取りたいと思っております。
全ての値をミリ秒値にして、合計値から差分を取るという方法を試しましたが、取るための計算(乗算)が多すぎるというところがあります。
何か円滑に割り出す方法はないでしょうか。

C++

1// 構造体 2struct STDATE 3{ 4 uint8_t Year; ///< 年 0~n 1970年+n年 5 uint8_t Month; ///< 月 1~12 6 uint8_t Day; ///< 日 1~31 7 uint8_t Hour; ///< 時 0~23 8 uint8_t Minutes; ///< 分 0~59 9 uint8_t Seconds; ///< 秒 0~59 10 uint16_t MilliSeconds; ///< ミリ秒 0~999 11};

C++

1//ミリ秒変換サンプル 2STDATE odate = 先データファイル読み込み; 3STDATE ndate = 後データファイル読み込み; 4uint64_t omsec = 0; 5omsec += odate.Year * 12 * 31 * 24 * 60 * 60 * 1000 6omsec += odate.Month * 31 * 24 * 60 * 60 * 1000 7omsec += odate.Day * 24 * 60 * 60 * 1000 8omsec += odate.Hour * 60 * 60 * 1000 9omsec += odate.Minutes * 60 * 1000 10omsec += odate.secounds * 1000; 11omsec += odate.Millisecounds; 12uint64_t nmsec = 0; 13omsec += ndate.Year * 12 * 31 * 24 * 60 * 60 * 1000 14omsec += ndate.Month * 31 * 24 * 60 * 60 * 1000 15omsec += ndate.Day * 24 * 60 * 60 * 1000 16omsec += ndate.Hour * 60 * 60 * 1000 17omsec += ndate.Minutes * 60 * 1000 18omsec += ndate.secounds * 1000; 19omsec += ndate.Millisecounds; 20 21uint64_t diff = nmsec - omsec;

開発環境

OS:Windows10
ツール:Visual Studio2010 Professional

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2019/09/26 11:38

ブラットフォーム(プログラムを稼働させているOS)は何でしょうか? Windowsとか、Linuxとか、macOSとか。OSの提供するAPIやシステムコールを使えば比較的簡単だと思います。自力でカレンダーの計算をしなければいけないのでしょうか。うるう年、うるう秒とか考えるとかなり面倒です。
JanTh1989

2019/09/26 11:59

質問に開発環境を追記しました。
Zuishin

2019/09/26 12:00

乗算が多いと言っても、最適化で全部消えて定数一つになると思いますが、そもそも自作する必要があるのかも疑問です。
Zuishin

2019/09/26 12:02

あと、差のみが必要なら、差をとってから乗算したほうが乗算の回数も減るしオーバーフローのリスクも減ります。
Zuishin

2019/09/26 12:10

というかよく見たら月の日数もうるう年も考慮してないからミリ秒は出ませんね。
JanTh1989

2019/09/28 05:07

1か所でしか使わないので、定数は考えていませんでした。 自作にする理由としましては、読み込むファイル(バイナリ)内に入っている日時情報バイト数に合わせて構造体化して読み込みたかったところにあります。 今後日時情報バイト数が変化することがあっても、それに合わせて自作構造体のメンバ型を変えれば済む、という形にしておきたかったこともあります。
guest

回答5

0

time_tに一旦変換してから計算してみる方式。うるう年にも対応できている・・・かもしれない。

C++

1#include <iostream> 2#include <ctime> 3 4// 構造体 5struct STDATE 6{ 7 uint8_t Year; ///< 年 0~n 1970年+n年 8 uint8_t Month; ///< 月 1~12 9 uint8_t Day; ///< 日 1~31 10 uint8_t Hour; ///< 時 0~23 11 uint8_t Minutes; ///< 分 0~59 12 uint8_t Seconds; ///< 秒 0~59 13 uint16_t MilliSeconds; ///< ミリ秒 0~999 14}; 15 16#define TMINITIALIZER_FROM_STDATE(p) { \ 17 .tm_sec = (p)->Seconds, \ 18 .tm_min = (p)->Minutes, \ 19 .tm_hour = (p)->Hour, \ 20 .tm_mday = (p)->Day, \ 21 .tm_mon = (p)->Month, \ 22 .tm_year = (p)->Year + 70, \ 23} 24 25int main(void) 26{ 27 //ミリ秒変換サンプル 28 STDATE odate = { 2018-1970, 9, 26, 10, 10, 10, 800 }; 29 STDATE ndate = { 2019-1970, 9, 26, 10, 10, 10, 600 }; 30 31 struct tm otm = TMINITIALIZER_FROM_STDATE(&odate); 32 struct tm ntm = TMINITIALIZER_FROM_STDATE(&ndate); 33 34 time_t otime = std::mktime(&otm); 35 time_t ntime = std::mktime(&ntm); 36 37 int64_t diff_msec = ((int64_t)ntime - (int64_t)otime) * 1000 + ndate.MilliSeconds - odate.MilliSeconds; 38 39 std::cout << diff_msec << std::endl; 40 41 return 0; 42}

投稿2019/09/26 14:00

nomuken

総合スコア1627

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

time_tに持ち込んでも自力でミリ秒の差分とっても計算コストは変わりません。

投稿2019/09/27 06:33

yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C++

1#include <iostream> 2#include <cstdint> 3using namespace std; 4 5struct STDATE { 6 uint8_t Year; ///< 年 0~n 1970年+n年 7 uint8_t Month; ///< 月 1~12 8 uint8_t Day; ///< 日 1~31 9 uint8_t Hour; ///< 時 0~23 10 uint8_t Minutes; ///< 分 0~59 11 uint8_t Seconds; ///< 秒 0~59 12 uint16_t MilliSeconds; ///< ミリ秒 0~999 13}; 14 15uint64_t msec(const STDATE &d) 16{ 17 static int M[] = { 306,337,0,31,61,92,122,153,184,214,245,275 }; 18 int m = d.Month, y = d.Year + 1970 - (m < 3); 19 return ((((((y*365 + y/4 - y/100 + y/400 + M[m-1] + d.Day) * 24LLU) + 20 d.Hour) * 60) + d.Minutes) * 60 + d.Seconds) * 1000 + d.MilliSeconds; 21} 22 23int main() 24{ 25 STDATE odate = { 1976 - 1970, 7, 24, 13, 59, 59, 999 }; 26 STDATE ndate = { 2019 - 1970, 9, 27, 3, 17, 12, 345 }; 27 uint64_t diff = msec(ndate) - msec(odate); 28 cout << diff << endl; 29}

投稿2019/09/26 18:27

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

https://qiita.com/Riliumph/items/841ebaf0d349ff6e1d79

こちらを参考にして、msを除きtmからtime_t型に変換して
ms部分は小数点にでも入れ込んで差分を取ればよろしいかと。

投稿2019/09/26 13:53

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

自作なら自分で実装する必要がありますね
結局、

全ての値をミリ秒値にして、合計値から差分を取るという方法

しかないと思います。
実際に実装してもそんなに処理が増えることもないと思いますが、どういうコードを書いてるんでしょうか。

投稿2019/09/26 11:33

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

JanTh1989

2019/09/26 11:58

ミリ秒変換サンプルを質問に追記しました。
y_waiwai

2019/09/26 12:24

・年月日から、西暦1年1月1日からの通算日数を求める ・通算日数と時分秒ミリ秒から通算ミリ秒を求める というふうに算出していきましょう。 そんなに計算量は多くありません
JanTh1989

2019/09/28 05:11 編集

計算手順まで提示頂きありがとうございます。 以下のような手順で実装してみました。 uint32_t _diffTime(STDATE aDate, STDATE rDate) { //[ STDATE型データをミリ秒に変換。 ] uint32_t aDay = ((aDate.Year + 1970) * 365 + aDate.Month) * 31 + aDate.Day; uint32_t aTime = (((aDay * 24 + aDate.Hour) * 60 + aDate.Minutes) * 60 + aDate.Seconds) * 1000 + aDate.MilliSeconds; uint32_t rDay = ((rDate.Year + 1970) * 365 + rDate.Month) * 31 + rDate.Day; uint32_t rTime = (((rDay * 24 + rDate.Hour) * 60 + rDate.Minutes) * 60 + rDate.Seconds) * 1000 + rDate.MilliSeconds; //[ 日時(ミリ秒)の差分値算出。 ] uint32_t diffTime = rTime - aTime; return diffTime; }
Zuishin

2019/09/28 05:15

これで 2 月 28 日 23 時 59 分 59 秒に作ったものと、3 月 1 日 0 時 0 分に作ったものの差を取ってみてください。1 秒にはなりませんよね?
y_waiwai

2019/09/28 06:59

ちなみに、「C言語 通算日数」でぐぐるとコードがいろいろ出てきます 通算日数を求める、通算日数から日付を求める、の2つを作っておけば、のちのち便利に使えますよ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問