strptime(3) преобразование строкового представления времени в структуру

ОБЗОР

#define _XOPEN_SOURCE /* См. feature_test_macros(7) */
#include <time.h>

char *strptime(const char *s, const char *format, struct tm *tm);

ОПИСАНИЕ

Функция strptime() является конвертирующей функцией, дополняющей strftime(3): она преобразует символьную строку, на которую указывает s, сохраняя значения в структуре tm (описывает время в виде компонент, broken-down time) согласно формата, заданного в format.

структура времени tm в виде компонент определена в <time.h>:

struct tm {
    int tm_sec;    /* секунды (0-60) */
    int tm_min;    /* минуты (0-59) */
    int tm_hour;   /* часы (0-23) */
    int tm_mday;   /* день месяца (1-31) */
    int tm_mon;    /* месяц (0-11) */
    int tm_year;   /* год - 1900 */
    int tm_wday;   /* день недели (0-6, воскресенье = 0) */
    int tm_yday;   /* день года (0-365, 1 января = 0) */
    int tm_isdst;  /* летнее время */
};

Дополнительную информацию о структуре tm смотрите в ctime(3).

Аргумент format является символьной строкой, состоящей из описателей поля и текстовых символов, напоминающей scanf(3). Каждый описатель поля состоит из символа % с последующим символом, который указывает на замену описателя поля. Остальные символы в строке format должны совпадать со строкой входных данных. Исключениями являются пробелы, которые совпадают с любым количеством пробелов в строке входных данных. Между любыми двумя описателями полей должно быть пустое место (пробелы) или другие алфавитно-цифровые символы.

Функция strptime() обрабатывает строку ввода слева направо. Каждый из трёх возможных входных элементов (пробел, буква или форматирующие символы) обрабатываются один за другим. Если ввод не соответствует строке форматирования, то функция прекращает работу. Оставшиеся части формата и данных не обрабатываются.

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

%%
Символ %.
%a или %A
Название дня недели согласно текущей локали, в форме аббревиатуры или полного имени.
%b, %B или %h
Название месяца согласно текущей локали, в форме аббревиатуры или полного имени.
%c
Дата и время, отображенные согласно текущей локали.
%C
Номер столетия (0-99).
%d или %e
День месяца (1-31).
%D
Эквивалент %m/%d/%y (американское представление даты, которое может запутать не американцев, особенно с учетом того, что %d/%m/%y широко используется в Европе. Форматом ISO 8601 является %Y-%m-%d).
%H
Час (0-23).
%I
Час на 12-часовом циферблате (1-12).
%j
Номер дня в году (1-366).
%m
Номер месяца (1-12).
%M
Минута (0-59).
%n
Обязательный пробел.
%p
Локализованный эквивалент AM или PM (примечание: его может не быть).
%r
Время по 12-ти часовым часам (используя AM или PM локали). В локали POSIX это эквивалентно %I:%M:%S %p. Если t_fmt_ampm пусто в поле LC_TIME текущей локали, то поведение не определено.
%R
Эквивалент %H:%M.
%S
Секунда (0-60; 60 может появляться для високосных секунд; ранее также допускалось появление 61).
%t
Обязательный пробел.
%T
Эквивалент %H:%M:%S.
%U
Номер недели в году, начинающейся с воскресенья (0-53). Первое воскресенье января является первым днем недели 1.
%w
Порядковый номер дня недели (0-6), воскресенье = 0.
%W
Номер недели в году, начинающейся с понедельника (0-53). Первый понедельник января является первым днем недели 1.
%x
Дата в локализованном формате представления.
%X
Время в локализованном формате представления.
%y
Год века (0-99). Если век никак не указывается, то года 69-99 относятся к двадцатому веку (с 1969 по 1999 включительно), а года в диапазоне 00-68 относятся к двадцать первому веку (с 2000 по 2068 включительно).
%Y
Год, включая столетие (например, 1991).

Некоторые описатели полей могут быть изменены модификаторами E или O, указывающими, что нужно использовать альтернативный формат или спецификацию. Если альтернативный формат или спецификация не существует в текущей локали, то используются неизменённые описатели полей.

Модификатор E указывает на то, что строка ввода может содержать альтернативные локале-зависимые версии представления даты и времени:

%Ec
Альтернативный формат представления даты и времени в текущей локали.
%EC
Альтернативный формат представления базового года в зависимости от текущей локали.
%Ex
Альтернативный формат представления даты в зависимости от текущей локали.
%EX
Альтернативный формат представления времени в зависимости от текущей локали.
%Ey
Альтернативный формат представления смещения от %EC в зависимости от текущей локали.
%EY
Альтернативный формат полного представления года.

Модификатор O указывает, что числовой ввод может производиться в альтернативном формате в зависимости от текущей локали:

%Od или %Oe
Число месяца с использованием альтернативных чисел локали; предшествующие нули можно ставить, но это необязательно.
%OH
Часы (0-24) с использованием альтернативных чисел локали.
%OI
Часы (1-12) с использованием альтернативных чисел локали.
%Om
Месяц с использованием альтернативных чисел локали.
%OM
Минуты с использованием альтернативных чисел локали.
%OS
Секунды с использованием альтернативных чисел локали.
%OU
Номер недели в году (воскресенье — первый день недели) с использованием альтернативных чисел локали.
%Ow
Обычный номер дня недели (воскресенье — нулевой день недели) с использованием альтернативных чисел локали.
%OW
Номер недели в году (понедельник — первый день недели) с использованием альтернативных чисел локали.
%Oy
Год (смещение от %C) с использованием альтернативных чисел локали.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

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

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes(7).
ИнтерфейсАтрибутЗначение
strptime() безвредность в нитяхбезвредно (MT-Safe env locale)

СООТВЕТСТВИЕ СТАНДАРТАМ

POSIX.1-2001, POSIX.1-2008, SUSv2.

ЗАМЕЧАНИЯ

В принципе, эта функция не инициализирует tm, а только сохраняет указанные значения. Это означает, что tm должна быть инициализирована до этого вызова. Существует небольшая разница между системами UNIX. Функция из glibc не не изменяет поля, которые не описаны явно, за исключением пересчитываемых полей tm_wday и tm_yday, если изменился один из элементов: день, месяц или год.

В glibc 2.0 спецификатор «y» (год столетия) указывает на год в диапазоне 1950-2049. А начиная с glibc 2.1 этот диапазон равен 1969-2068.

Замечания по glibc

Для симметрии glibc пытается поддерживать в strptime() тот же формат символов что и в strftime(3) (в большинстве случаев, соответствующие поля анализируются, но поле в tm не изменяется). В результате:
%F
Эквивалентно %Y-%m-%d в формате ISO 8601.
%g
Год, соответствующий номеру недели по ISO, но без номера века (0-99).
%G
Год, соответствующий номеру недели по ISO (например, 1991).
%u
День недели в цифровом формате (1-7, где понедельник — 1).
%V
Номер недели в виде числа (1-53) по стандарту ISO 8601:1988. Если неделя (начинающаяся с понедельника) содержит 1 января и имеет 4 или более дней в новом году, то это первая неделя. Иначе это последняя неделя предыдущего года, а следующая неделя первая.
%z
Часовой пояс согласно спецификациям стандарта RFC-822/ISO 8601.
%Z
Название часового пояса.

Аналогично, учитывая расширения GNU для strftime(3), %k принято считать синонимом %H, а %l — синонимом для %I, и %P синонимом %p. И

%s
Количество секунд с начала эпохи, с 1970-01-01 00:00:00 +0000 (UTC). Если нет поддержки для високосных секунд, то они не учитываются.

В реализации glibc не требуется пустого места (пробелов) между двумя описателями полей.

ПРИМЕР

Следующий пример демонстрирует использование strptime() и strftime(3).

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int
main(void)
{
    struct tm tm;
    char buf[255];
    memset(&tm, 0, sizeof(struct tm));
    strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm);
    strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm);
    puts(buf);
    exit(EXIT_SUCCESS);
}