Преобразование даты / времени: строковое представление в time_t

Как преобразовать строку даты в формате "MM-DD-YY HH:MM:SS" в значение time_t в C или C++?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
14
0
25 782
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Боюсь, что в Standard C / C++ их нет. Существует функция POSIX strptime, которая может преобразовывать в struct tm, который затем можно преобразовать в time_t с помощью mktime.

Если вы стремитесь к кросс-платформенной совместимости, лучше используйте boost::date_time, который имеет для этого сложные функции.

Ответ принят как подходящий

Используйте strptime() для анализа времени в struct tm, затем используйте mktime() для преобразования в time_t.

strptime (), похоже, недоступен в Windows. Есть ли хорошая альтернатива?

An̲̳̳drew 26.11.2008 22:17

Не знаю, есть ли хорошая альтернатива для Windows, есть несколько реализаций с открытым исходным кодом, которые вы могли бы использовать. В качестве альтернативы, если вы знаете, что дата всегда будет в указанном вами формате, вы можете проанализировать ее в struct tm, возможно, используя sscanf, а затем использовать mktime для получения time_t.

Robert Gamble 26.11.2008 22:23

вот пример stackoverflow.com/a/11213640/1115059

Jaydeep Solanki 19.09.2014 05:46

@ An̲̳̳drew strptime() часто доступен в Windows с компилятором gcc. Доступность - это проблема компилятора, а не ОС.

chux - Reinstate Monica 30.01.2018 03:07

Библиотека даты и времени Boost должна помочь; в частности, вы можете посмотреть http://www.boost.org/doc/libs/1_37_0/doc/html/date_time/date_time_io.html

В отсутствие strptime вы можете использовать sscanf для синтаксического анализа данных в struct tm, а затем вызвать mktime. Не самое элегантное решение, но оно сработает.

    static time_t MKTimestamp(int year, int month, int day, int hour, int min, int sec)
{
    time_t rawtime;
    struct tm * timeinfo;

    time ( &rawtime );
    timeinfo = gmtime ( &rawtime );
    timeinfo->tm_year = year-1900 ;
    timeinfo->tm_mon = month-1;
    timeinfo->tm_mday = day;
    timeinfo->tm_hour = hour;
    timeinfo->tm_min = min;
    timeinfo->tm_sec = sec;
    timeinfo->tm_isdst = 0; // disable daylight saving time

    time_t ret = mktime ( timeinfo );

    return ret;
}

 static time_t GetDateTime(const std::string pstr)
{
    try 
    {
        // yyyy-mm-dd
        int m, d, y, h, min;
        std::istringstream istr (pstr);

        istr >> y;
        istr.ignore();
        istr >> m;
        istr.ignore();
        istr >> d;
        istr.ignore();
        istr >> h;
        istr.ignore();
        istr >> min;
        time_t t;

        t=MKTimestamp(y,m,d,h-1,min,0);
        return t;
    }
    catch(...)
    {

    }
}

Обратите внимание, что strptime, упомянутый в принятом ответе, не переносится. Вот удобный код C++ 11, который я использую для преобразования строки в std :: time_t:

static std::time_t to_time_t(const std::string& str, bool is_dst = false, const std::string& format = "%Y-%b-%d %H:%M:%S")
{
    std::tm t = {0};
    t.tm_isdst = is_dst ? 1 : 0;
    std::istringstream ss(str);
    ss >> std::get_time(&t, format.c_str());
    return mktime(&t);
}

Вы можете назвать это так:

std::time_t t = to_time_t("2018-February-12 23:12:34");

Вы можете найти параметры формата строки здесь.

1) Код не устанавливает член tm_isdst. Несоблюдение этого правила может привести к противоречивым результатам. 2) struct tm допускает добавление дополнительных членов, которые выигрывают при инициализации. Может, std::tm t = { 0 };? 3) Строка месяца OP является числовой, а не буквенной. Используйте "%m", а не "%b". 4) OP использовал другой порядок, чем YMD hms.

chux - Reinstate Monica 30.01.2018 03:42

Я добавил опцию dst. Инициализация с 0 - хорошая идея. Остальное можно легко настроить в соответствии с индивидуальными требованиями.

Shital Shah 23.02.2018 10:07

best way to convert a date string, formatted as "MM-DD-YY HH:MM:SS", to a time_t

Ограничение кода стандартными функциями библиотеки C ищет инверсию strftime(). Чтобы расширить общую идею @ Роб, используется sscanf().

Используйте "%n" для обнаружения завершенного сканирования

time_t date_string_to_time(const char *date) {
  struct tm tm = { 0 }; // Important, initialize all members
  int n = 0;
  sscanf(date, "%d-%d-%d %d:%d:%d %n", &tm.tm_mon, &tm.tm_mday, &tm.tm_year,
      &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &n);
  // If scan did not completely succeed or extra junk
  if (n == 0 || date[n]) {
    return (time_t) -1;
  }
  tm.tm_isdst = -1; // Assume local daylight setting per date/time
  tm.tm_mon--;      // Months since January
  // Assume 2 digit year if in the range 2000-2099, else assume year as given
  if (tm.tm_year >= 0 && tm.tm_year < 100) {
    tm.tm_year += 2000;
  }
  tm.tm_year -= 1900; // Years since 1900
  time_t t = mktime(&tm);
  return t;
}

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

Примечание: предполагается, что «ММ-ДД-ГГ ЧЧ: ММ: СС» - это время местный.

Интересно, что я так и не нашел варианта использования %n, так как всегда использовал возвращаемое значение *scanf, чтобы гарантировать, что все аргументы были просканированы. Однако похоже, что %n (как вы его используете) делает это. и гарантирует, что после ожидаемой строки не будет лишних gumpf. В настоящее время я не часто узнаю что-то новое о C, так что спасибо :-)

paxdiablo 30.01.2018 03:40

@paxdiablo Спасибо. " %n", как правило, помогает обнаруживать любой требуемый конечный текст, чего не различает возвращаемое значение. Например. "%d xyz %n".

chux - Reinstate Monica 30.01.2018 03:46

Другие вопросы по теме