С++: как получить фактическое время со временем и местным временем?

Я ищу способ сэкономить время в стиле HH::MM::SS на С++. Я увидел здесь, что есть много решений, и после небольшого исследования я выбрал time и localtime. Однако кажется, что функция localtime немного сложна, поскольку она говорит:

Все вызовы localtime и gmtime используют одну и ту же статическую структуру, поэтому каждый вызов перезаписывает результаты предыдущего вызова.

Проблема, которую это вызывает, показана в следующем фрагменте кода:

#include <ctime>
#include <iostream>
using namespace std;

int main() {
time_t t1 = time(0);   // get time now
struct tm * now = localtime( & t1 );

std::cout << t1 << std::endl;
sleep(2);
time_t t2 = time(0);   // get time now
struct tm * now2 = localtime( & t2 );
std::cout << t2 << std::endl;

cout << (now->tm_year + 1900) << '-'
     << (now->tm_mon + 1) << '-'
     <<  now->tm_mday << ", "
     << now->tm_hour << ":" << now->tm_min << ":" << now->tm_sec
     << endl;

cout << (now2->tm_year + 1900) << '-'
     << (now2->tm_mon + 1) << '-'
     <<  now2->tm_mday << ", "
     << now2->tm_hour << ":" << now2->tm_min << ":" << now2->tm_sec
     << endl;
}

Типичный вывод для этого:

1320655946
1320655948
2011-11-7, 9:52:28
2011-11-7, 9:52:28

Как видите, временные метки time_t верны, но местное время все портит.

Мой вопрос: как преобразовать временную метку типа time_t в удобочитаемое время?


person seb    schedule 07.11.2011    source источник


Ответы (4)


Если вас беспокоит повторный вход в localtime и gmtime, есть localtime_r и gmtime_r, которые могут обрабатывать несколько вызовов.

Когда дело доходит до форматирования времени по своему вкусу, проверьте функцию strftime.

person Some programmer dude    schedule 07.11.2011

вызов localtime() сохраняет результаты во внутреннем буфере.

Каждый раз, когда вы ее вызываете, вы перезаписываете буфер.
Альтернативным решением может быть создание копии буфера.

time_t      t1  = time(0);           // get time now
struct tm* now  = localtime( & t1 ); // convert to local time
struct tm  copy = *now;              // make a local copy.
 //     ^^^ notice no star.

Но обратите внимание: единственный раз, когда вы должны преобразовывать местное время, это когда вы отображаете значение. В остальное время вы должны просто сохранять время в формате UTC (для хранения и обработки). Так как вы только конвертируете объекты для отображения, конвертируйте, а затем сразу печатайте, и тогда ничего не пойдет не так.

person Martin York    schedule 07.11.2011
comment
+1 За уточнение, что мне нужно сделать преобразование только в конце. Спасибо! - person seb; 07.11.2011

localtime имеет то, что лучше всего считается устаревшим интерфейсом. Например, его нельзя использовать в многопоточном коде. В многопоточной среде вы можете использовать localtime_r под Posix или localtime_s под Windows. В противном случае все, что вам нужно сделать, это сохранить результаты:

tm then = *localtime( &t1 );
//  ...
tm now = *localtime( &t2 );

Однако было бы более идиоматично вызывать localtime
только непосредственно перед форматированием вывода, например:

std::string
timestampToString( time_t timeAndDate )
{
    char results[100];
    if ( strftime( results, sizeof( results ), "%Y-%m-%d, %H:%M:%S", 
                localtime( &timeAndDate) ) == 0 ) {
        assert( 0 );
    }
    return results;
}

а затем пишет:

std::cout << formatTime( t1 ) << std::endl;

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

person James Kanze    schedule 07.11.2011

Вы можете запустить непрерывные часы, используя следующий код. Это прекрасно работает.

#include<iostream> 
#include <Windows.h> 
#include<ctime> 
using namespace std;

void main() {
  while(true) {
    system("cls"); //to clear screen
    time_t tim;
    time(&tim); 
    cout << ctime(&tim); 
    Sleep(1);
  }
}
person Snehal    schedule 03.07.2014
comment
Я думаю, что это не отвечает на вопрос. (как отображать time_t в удобочитаемом формате) - person andrel; 03.07.2014