3

標準の ISO 8601 タイムスタンプが与えられた場合、元のタイムスタンプの 20 分前と 20 分後の別のタイムスタンプを取得する簡単な方法はありますか?

たとえば、与えられた

 2010-01-25 18:02:00

1 つまたは 2 つの関数を返したいのですが 2010-01-25 17:48:002010-01-25 18:22:00

私があきらめた解決策はかなり面倒ですs.substr(14,2)。分s.substr(12,2)を取得して時間を取得し、時と分の文字列を int に変換し、60 を超えるか 0 を下回る場合は、条件付きで分の値を減算または加算します。これを行うためのより良い/より簡単な方法はありますか?

4

2 に答える 2

9

あなたは出来る:

  1. struct tm 文字列をusingstd::get_timeに変換します。
  2. 変更しますstruct tm(範囲を考慮する必要はありません)。
  3. struct tm を使用してmktime正規化します。
  4. 使用して印刷するstruct tm std::put_time

#include <ctime>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>

std::string increase_minutes(const std::string& input, int delta) {
    struct tm tm;
    constexpr auto format = "%Y-%m-%d %T";

    std::istringstream iss (input);
    iss >> std::get_time(&tm, format);
    tm.tm_min += delta;
    mktime(&tm);

    std::ostringstream oss;
    oss << std::put_time(&tm, format);
    return oss.str();
}


int main() {
    auto s = "2012-12-31 23:59:00";
    std::cout << increase_minutes(s, 20) << std::endl;
    std::cout << increase_minutes(s, -20) << std::endl;
}

std::get_timestd::put_timeはg++/libstdc++には存在しないことに注意してください。sscanfC関数またはを使用して文字列を解析し、を使用して文字列を出力する必要がある場合がありstrptimeますstrftimeC++の日付と時刻も参照してください。


編集:ジェネリックで変更したい場合は、直接std::chrono::duration操作する方が良いでしょう。std::chrono::time_point以下に示すように、2段階の変換でaからtime_pointを作成できます。time_point↔time_t↔structtm struct tm

#include <ctime>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <chrono>

template <typename R, typename P>
std::string increase_iso_time(const std::string& input, 
                              const std::chrono::duration<R, P>& duration) {
    struct tm tm;
    constexpr auto format = "%Y-%m-%d %T";

    std::istringstream iss (input);
    iss >> std::get_time(&tm, format);
    auto time = mktime(&tm);
    auto tp = std::chrono::system_clock::from_time_t(time);

    tp += duration;

    time = std::chrono::system_clock::to_time_t(tp);
    tm = *localtime(&time);
    std::ostringstream oss;
    oss << std::put_time(&tm, format);
    return oss.str();
}

int main() {
    auto s = "2012-12-31 23:59:00";
    std::cout << increase_iso_time(s, std::chrono::minutes(20)) << std::endl;
    std::cout << increase_iso_time(s, - std::chrono::hours(4)
                                      - std::chrono::minutes(20)) << std::endl;
}
于 2012-12-09T19:09:17.120 に答える
3

mktime()C または C++ 標準から検索します。strptime()ISO 8601 時刻を に変換するようなものが必要ですstruct tm(またはsscanf()、または ... を使用できます)。次に、構造の 2 つのコピーを作成tm_minし、一方を +20 で、もう一方を -20 で調整し、 を呼び出しmktime()、次にを呼び出しますstrftime()

これは、C および C++98、C++2003、C++2011 で機能します。C++2011 でのみ動作させたい場合は、に移動する必要がありますstd::chrono

サンプルコード

このコードはヘッダーのために C++ 用ですが、 と に変更することで C に変換でき<time.h>ます<stdio.h>。はい、おそらく「優れた」C++ とは見なされません。確かに、いくつかのインターフェイスの決定が必要になります。しかし、それは仕事を成し遂げます。(純粋な C++ の場合は、への参照を削除できますstruct。)

#include <ctime>
#include <cstdio>

static void delta_t(const char *otime, int delta)
{
    struct tm tm1;
    int n;
    if ((n = sscanf(otime, "%4d-%2d-%2d %2d:%2d:%2d", &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday,
                    &tm1.tm_hour, &tm1.tm_min, &tm1.tm_sec)) != 6)
    {
        printf("%s: failed %d\n", otime, n);
        return;
    }
    printf("%.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", tm1.tm_year, tm1.tm_mon, tm1.tm_mday,
            tm1.tm_hour, tm1.tm_min, tm1.tm_sec);

    tm1.tm_isdst = -1;
    tm1.tm_year -= 1900;
    tm1.tm_mon--;
    struct tm tm2 = tm1;
    tm2.tm_min += delta;
    struct tm tm3 = tm1;
    tm3.tm_min -= delta;
    mktime(&tm2);
    mktime(&tm3);
    char dt1[20];
    char dt2[20];
    char dt3[20];
    strftime(dt1, sizeof(dt1), "%Y-%m-%d %H:%M:%S", &tm1);
    strftime(dt2, sizeof(dt2), "%Y-%m-%d %H:%M:%S", &tm2);
    strftime(dt3, sizeof(dt3), "%Y-%m-%d %H:%M:%S", &tm3);

    printf("Input: %s\n", otime);
    printf("Date1: %s\n", dt1);
    printf("Date2: %s\n", dt2);
    printf("Date3: %s\n", dt3);
}

int main(void)
{
    delta_t("2010-01-25 18:02:00", 20);
    delta_t("2012-12-31 23:59:00", 20);
    return(0);
}

サンプル出力:

2010-01-25 18:02:00
Input: 2010-01-25 18:02:00
Date1: 2010-01-25 18:02:00
Date2: 2010-01-25 18:22:00
Date3: 2010-01-25 17:42:00
2012-12-31 23:59:00
Input: 2012-12-31 23:59:00
Date1: 2012-12-31 23:59:00
Date2: 2013-01-01 00:19:00
Date3: 2012-12-31 23:39:00
于 2012-12-09T19:35:43.490 に答える