Last active
February 9, 2021 02:13
-
-
Save komasaru/234f735691d67b481973059dcbf67d50 to your computer and use it in GitHub Desktop.
C++ source code to calculate a mean of 2 timespecs.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*********************************************************** | |
2つの時刻(timespec)の平均を計算 | |
DATE AUTHOR VERSION | |
2021.02.06 mk-mode.com 1.00 新規作成 | |
Copyright(C) 2020 mk-mode.com All Rights Reserved. | |
---------------------------------------------------------- | |
引数 : JST_1 JST_2 | |
書式:最大23桁の数字 | |
(先頭から、西暦年(4), 月(2), 日(2), 時(2), 分(2), 秒(2), | |
1秒未満(9)(小数点以下9桁(ナノ秒)まで)) | |
---------------------------------------------------------- | |
$ g++92 -std=c++17 -Wall -O2 --pedantic-errors -o mean_time mean_time.cpp | |
***********************************************************/ | |
#include <cstdlib> // for EXIT_XXXX | |
#include <ctime> | |
#include <iomanip> | |
#include <iostream> | |
#include <string> | |
/* | |
* @brief Time addition | |
* | |
* @param[in] 時刻A (timespec) | |
* @param[in] 時刻B (timespec) | |
* @return 時刻 (timespec) | |
*/ | |
struct timespec time_add(struct timespec ts_a, struct timespec ts_b) { | |
struct timespec ts; | |
try { | |
ts.tv_sec = ts_a.tv_sec + ts_b.tv_sec; | |
ts.tv_nsec = ts_a.tv_nsec + ts_b.tv_nsec; | |
if(ts.tv_nsec >= 1e9){ | |
++ts.tv_sec; | |
ts.tv_nsec -= 1e9; | |
} | |
if (ts.tv_nsec < 0) { | |
--ts.tv_sec; | |
ts.tv_nsec += 1e9; | |
} | |
} catch (...) { | |
throw; | |
} | |
return ts; | |
} | |
/* | |
* @brief Mean of 2 Timespec | |
* | |
* @param[in] 時刻A (timespec) | |
* @param[in] 時刻B (timespec) | |
* @return 時刻 (timespec) | |
*/ | |
struct timespec time_mean(struct timespec ts_a, struct timespec ts_b) { | |
struct timespec ts; | |
long int a; // 商 | |
long int r; // 剰余 | |
try { | |
ts = time_add(ts_a, ts_b); | |
a = ts.tv_sec / 2; | |
r = ts.tv_sec - a * 2; | |
ts.tv_sec = a; | |
ts.tv_nsec += r * 1e9; | |
ts.tv_nsec /= 2; | |
if (ts.tv_nsec < 0) { | |
ts.tv_nsec += 1e9; | |
--ts.tv_sec; | |
} | |
} catch (...) { | |
throw; | |
} | |
return ts; | |
} | |
/* | |
* @brief 日時文字列生成 | |
* | |
* @param[in] 日時 (timespec) | |
* @return 日時文字列 (string) | |
*/ | |
std::string gen_time_str(struct timespec ts) { | |
struct tm t; | |
std::stringstream ss; | |
std::string str_tm; | |
try { | |
localtime_r(&ts.tv_sec, &t); | |
ss << std::setfill('0') | |
<< std::setw(4) << t.tm_year + 1900 << "-" | |
<< std::setw(2) << t.tm_mon + 1 << "-" | |
<< std::setw(2) << t.tm_mday << " " | |
<< std::setw(2) << t.tm_hour << ":" | |
<< std::setw(2) << t.tm_min << ":" | |
<< std::setw(2) << t.tm_sec << "." | |
<< std::setw(9) << ts.tv_nsec; | |
return ss.str(); | |
} catch (...) { | |
throw; | |
} | |
} | |
int main(int argc, char* argv[]) { | |
unsigned int i; | |
std::string tm_str; | |
unsigned int s_tm; // size of time string | |
unsigned int s_nsec; // size of nsec string | |
struct tm t; | |
struct timespec ts[2]; // 時刻 A, B | |
struct timespec ts_m; // 時刻 A, B の平均 | |
try { | |
// 日付取得 | |
if (argc < 3) { | |
std::cout << "[USAGE] ./mean_timespec JST_1 JST_2" << std::endl; | |
return EXIT_SUCCESS; | |
} | |
// コマンドライン引数より取得 | |
for (i = 0; i < 2; ++i) { | |
tm_str = argv[i + 1]; | |
s_tm = tm_str.size(); | |
if (s_tm > 23) { | |
std::cout << "[ERROR] Over 23-digits!" << std::endl; | |
return EXIT_FAILURE; | |
} | |
t = {}; | |
std::istringstream is(tm_str); | |
is >> std::get_time(&t, "%Y%m%d%H%M%S"); | |
ts[i].tv_sec = mktime(&t); | |
ts[i].tv_nsec = 0; | |
s_nsec = s_tm - 14; | |
if (s_tm > 14) { | |
ts[i].tv_nsec = std::stod( | |
tm_str.substr(14, s_nsec) + std::string(9 - s_nsec, '0')); | |
} | |
} | |
std::cout << " TIME-A: " << gen_time_str(ts[0]) << std::endl; | |
std::cout << " TIME-B: " << gen_time_str(ts[1]) << std::endl; | |
// 2つの時刻の平均を変換 | |
ts_m = time_mean(ts[0], ts[1]); | |
std::cout << "MEAN(A, B): " << gen_time_str(ts_m) << std::endl; | |
} catch (...) { | |
std::cerr << "EXCEPTION!" << std::endl; | |
return EXIT_FAILURE; | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment