Skip to content

Instantly share code, notes, and snippets.

@komasaru
Last active February 9, 2021 02:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save komasaru/234f735691d67b481973059dcbf67d50 to your computer and use it in GitHub Desktop.
Save komasaru/234f735691d67b481973059dcbf67d50 to your computer and use it in GitHub Desktop.
C++ source code to calculate a mean of 2 timespecs.
/***********************************************************
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