std chrono 1 час неверен при преобразовании ctime в char*

Я пытаюсь отобразить разницу между точками времени с высоким разрешением в строке типа 00:00:00. Моя проблема в том, что время составляет +1 час, когда я его печатаю.

#include <chrono>
#include <ctime>
#include <iostream>
#include <thread>

using namespace std;
using namespace chrono;

int main(int argc, char **argv) {
    auto start = high_resolution_clock::now();
    this_thread::sleep_for(seconds(1));
    auto stop = high_resolution_clock::now();
    auto result = stop - start;
    time_t t = duration_cast<seconds>(result).count();
    cout << ctime(&t) << endl;
    return EXIT_SUCCESS;
}

Это печатает

Thu Jan 1 01:00:01 1970

Пока я ожидаю, что он напечатает

Thu Jan 1 00:00:01 1970

Тем не менее, следующие отпечатки 1:

cout << (int) duration_cast<seconds>(result).count() << endl;

Может это как-то связано с часовым поясом? Любая помощь приветствуется!


person fonZ    schedule 08.10.2014    source источник
comment
Я давно не использовал ctime, но документация кажется чтобы указать, что время преобразуется с использованием localtime.   -  person Retired Ninja    schedule 09.10.2014
comment
localtime возвращает структуру tm*. Я мог бы отредактировать время, но я думаю, что оно должно быть правильным, а не добавлять 1 час, как сейчас.   -  person fonZ    schedule 09.10.2014
comment
Если вы не хотите, чтобы часовой пояс использовался, выполните преобразование, используя функцию, которая не использует часовой пояс, возможно, gmtime или любую другую альтернативу.   -  person Retired Ninja    schedule 09.10.2014
comment
@RetiredNinja вау, gmtime спасает меня! Я попытался и получил ожидаемый результат, большое спасибо. Напишите ответ с ним и плохо принять его.   -  person fonZ    schedule 09.10.2014
comment
привет @fonZ, я обновил свой ответ. Вы должны быть в состоянии пойти дальше с этим.   -  person Wug    schedule 09.10.2014


Ответы (1)


Обсудив в комментариях, что именно вам нужно, я придумал это:

size_t MkTimestamp(char *output, size_t size)
{
    milliseconds ms = duration_cast<milliseconds>(system_clock::now().time_since_epoch());
    seconds s = duration_cast<seconds>(ms);
    time_t ctime = (time_t) s.count();
    tm components;
    size_t return_value = 0;

    if (!localtime_r(&ctime, &components)) return 0;
    if ((return_value = strftime(output, size, "%F %T:XXX", &components)) == 0) return 0;

    int ms_d1 = ms.count() / 100 % 10, ms_d2 = ms.count() / 10 % 10, ms_d3 = ms.count() % 10;
    output[return_value - 3] = ms_d1 + '0';
    output[return_value - 2] = ms_d2 + '0';
    output[return_value - 1] = ms_d3 + '0';
    return return_value;
}

Короче говоря, вы даете ему символьный буфер и его размер, и он записывает в него метку времени (если буфер слишком мал, он возвращает ноль, в противном случае он возвращает общее количество записанных символов, включая завершающий нуль). Если вам нужна эта метка времени как std::string, вы можете использовать конструктор среза std::string:

char buffer[64];
string timestamp(buffer, MkTimestamp(buffer, sizeof buffer));

Строковый конструктор будет считывать до нулевого ограничителя, если MkTimestamp завершится успешно, и создаст пустую строку, если он завершится ошибкой. Возможно, вы могли бы объединить этот шаг в MkTimestamp, если бы захотели.

Это отличается от вашей первой попытки следующим образом:

  • Поскольку вы пытаетесь создать отметку времени, вам лучше использовать абсолютное, а не относительное время.
  • Поскольку мы хотим использовать абсолютное время, мы должны использовать system_clock, потому что это единственные часы, которые на самом деле дают значения time_point, которые можно осмысленно преобразовать в значения time_t, которые будут принимать старые функции семейства C. (Иногда эти двое часов имеют одну и ту же эпоху или даже одни и те же часы. Но не всегда.)
  • Я выбрал другой формат времени. Вы можете изменить это, если хотите, это не составит труда. Я настоятельно рекомендую вам оставить заполнители миллисекунд в строке формата, чтобы вам не нужно было выполнять какие-либо тесты длины, пока strftime завершается успешно.

Отметить, где следует отдать должное (другие ответы stackoverflow, на которые я ссылался при написании этого ответа)

Исходный ответ:

Вот ideone с вашим кодом. (Обратите внимание, что проблема, которую вы описываете, не возникает.) Кроме того, вы отсутствует #include <thread>.

Кроме того, документация для ctime() указывает, что его аргументом должна быть календарная дата. . Вы передаете ему интервал в одну секунду, что само по себе более или менее бессмысленно. Вы, вероятно, правы, что он показывает ровно один час из-за проблемы с интерпретацией часового пояса.

Я не могу ответить лучше без более подробной информации о том, что вы на самом деле пытаетесь сделать.

person Wug    schedule 08.10.2014
comment
Не было ни одного до редактирования, когда я начал писать ответ. - person Wug; 09.10.2014
comment
я знаю ... но я думал, что люди, читающие этот пост, поймут, что это относится к программе, у которой есть главная ... поэтому я добавил ее. - person fonZ; 09.10.2014
comment
что касается того, что я пытаюсь сделать, я пытаюсь напечатать строковое представление прошедшего времени. 00:00:01, а не 01:00:01. Меня беспокоит 1 час, потому что прошла всего 1 секунда, и, насколько я знаю, преобразование в time_t является законным. - person fonZ; 09.10.2014
comment
Если все, что вам нужно, это прошедшее время, то вам не следует пытаться напечатать его с помощью функции, которая не обрабатывает прошедшее время. Используйте свой второй метод. - person Wug; 09.10.2014
comment
Так для вас он печатает 00:00:00? На этом ideone я вижу, что он печатает правильно? - person fonZ; 09.10.2014
comment
Я не запускал его локально. Почему нельзя просто использовать (int) duration_cast<seconds>(result).count()? - person Wug; 09.10.2014
comment
Поскольку мне нужна метка времени, мне нужно показать миллисекунды микро и нано, так что это будет длинная строка чисел для чтения, если мы говорим о паре секунд или даже минут. Вот почему я пытаюсь сделать его читабельным. - person fonZ; 09.10.2014
comment
Подождите немного, и я получу что-нибудь более близкое к тому, что вам нужно. - person Wug; 09.10.2014