Функции работы с датой и временем

Язык Си / Функции работы с датой и временем

 

Для работы с системной датой и временем используется библиотека time.h.

Типы, определенные в библиотеке time.h

Тип Описание
size_t Целочисленный тип, возвращаемый операцией sizeof.
clock_t Арифметический тип, подходящий для представления времени.
time_t Арифметический тип, подходящий для представления времени.
struct tm Структурный тип, содержащий компоненты календарного времени.

Для определения текущего календарного времени используется функция

 
time_t time(NULL);

Данная функция возвращает время в секундах начиная с 1 января 1970 г.

Например,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
char * settime(struct tm *u)
{
  char s[40];
  char *tmp;
  for (int i = 0; i<40; i++) s[i] = 0;
  int length = strftime(s, 40, "%d.%m.%Y %H:%M:%S, %A", u);
  tmp = (char*)malloc(sizeof(s));
  strcpy(tmp, s);
  return(tmp);
}
int main() 
{
  struct tm *u;
  char *f;
  system("chcp 1251");
  system("cls");
  const time_t timer = time(NULL);
  u = localtime(&timer);
  f = settime(u);
  printf("%ld соответствует ", timer);
  puts(f);
  getchar();
  return 0;
}

Дата и время

Структура tm имеет вид

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


Функция
 
struct tm *localtime(const time_t *ptm);

преобразует календарное время, указанное ptm, сохраняет его в структуре tm и возвращает указатель на нее.

Функция
 
time_t mktime(struct tm *timeptr);

осуществляет обратное преобразование.

Функция
 
clock_t clock (void);

возвращает наилучшее приближение процессорного времени, прошедшего с момента запуска программы; для получения времени в секундах значение необходимо разделить на константу, определенную в библиотеке time.h:
 
#define CLOCKS_PER_SEC 1000


Если время не доступно или не может быть представлено, возвращает (clock_t) (-1).

Функция
 
 
 
 
 
size_t strftime(
char *restrict s, // указатель на выходную строку
size_t max,    // максимальный размер выходной строки
const char *restrict fmt, // указатель на строку формата
const struct tm *restrict tmpt); // указатель на структуру tm

копирует строку fmt в строку s, заменяя спецификаторы формата в fmt соответствующими данными, взятыми из содержимого структуры времени, на которое указывает tmpt; в строку s помещается не более max символов.

Функция возвращает количество символов (исключая нулевой) в результирующей строке. Если результирующая строка (включая нулевой символ) содержит больше, чем max символов, функция возвращает 0, а содержимое s не определено.

Спец. Назначение
%a Локальное сокращенное название дня недели
%A Локальное полное название дня недели
%b Локальное сокращенное название месяца
%B Локальное полное название месяца
%c Локальный разделитель даты и времени
%d День месяца в виде десятичного числа (01-31)
%D Эквивалент %m%d%y
%e День месяца (десятичное число): однозначные числа дополнены пробелом
%F Эквивалент %Y-%m-%d
%g Последние два разряда года (00-99)
%G Год в виде десятичного числа
%H Часы (по 24-часовой шкале) в виде десятичного числа (00-23)
%I Часы (по 12-часовой шкале) в виде десятичного числа (01-12)
%j День года в виде десятичного числа (001-366)
%m Месяц в виде десятичного числа (01-12)
%n Символ новой строки
%M Минуты в виде десятичного числа (00-59)
%p Локальный эквивалент a.m./p.m. для 12-часовой временной шкалы
%r Локальное 12-часовое время
%R Эквивалент %H:%M
%S Секунды в виде десятичного числа (00-61)
%t Символ горизонтальной табуляции
%T Эквивалент %H:%M:%S
%u Номер дня недели (1-7), где 1 соответствует понедельнику
%U Номер недели в году, считая воскресенье первым днем недели (00-53)
%w Номер дня недели в виде десятичного числа, начиная с воскресенья (0-6)
%W Номер недели в году, считая понедельник первым днем недели (00-53)
%y Год без века в виде десятичного числа (00-99)
%Y Год с веком в виде десятичного числа
%z Смещение от UTC ("-800" означает на 8 ч по Гринвичу западнее).
%Z Наименование часового пояса (если доступно)
%% % (то есть знак процента).

Функция, позволяющая вывести день недели на русском языке

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <time.h>
char * settime(struct tm *u)
{
  char s[40];
  char *tmp;
  for (int i = 0; i<40; i++) s[i] = 0;
  int length = strftime(s, 40, "%d.%m.%Y %H:%M:%S ", u);
  switch (u->tm_wday)
  {
    case 0: strcpy(s + length, " воскресенье"); break;
    case 1: strcpy(s + length, " понедельник"); break;
    case 2: strcpy(s + length, " вторник");     break;
    case 3: strcpy(s + length, " среда");       break;
    case 4: strcpy(s + length, " четверг");     break;
    case 5: strcpy(s + length, " пятница");     break;
    case 6: strcpy(s + length, " суббота");     break;
  }
  tmp = (char*)malloc(sizeof(s));
  strcpy(tmp, s);
  return(tmp);
}
int main()
{
  struct tm *u;
  char *f;
  system("chcp 1251");
  system("cls");
  const time_t timer = time(NULL);
  u = localtime(&timer);
  f = settime(u);
  printf("%ld соответствует ", timer);
  puts(f);
  getchar();
  return 0;
}

Результат выполнения
Дата и время

Добавление нескольких дней к текущему времени

Рассмотрим еще один пример. Допустим, требуется добавить несколько дней к текущей дате.
Реализация на Си

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <time.h>
#define ADD_DAYS 300
int main()
{
  struct tm *u;
  char s1[40] = { 0 }, s2[40] = { 0 };
  const time_t timer = time(NULL);
  u = localtime(&timer);
  strftime(s1, 80, "%d.%m.%Y %H:%M:%S ", u);
  printf("%s\n", s1);
  u->tm_mday += ADD_DAYS;
  time_t next = mktime(u);
  u = localtime(&next);
  strftime(s2, 80, "%d.%m.%Y %H:%M:%S ", u);
  printf("%s\n", s2);
  getchar();
  return 0;
}

Результат выполнения
Добавление нескольких дней к текущей дате

Реализация функции задержки

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <time.h>
void delay(int ms) // аргумент- требуемое время задержки в миллисекундах
{
  int c = clock() + ms;
  while (clock() < c);
}
int main() 
{
  printf("clock = %d\n", clock());
  delay(1000);
  printf("clock = %d\n", clock());
  getchar();
  return 0;
}

Результат выполнения
Функция задержки


Назад: Язык Си

Комментариев к записи: 17

  • ключевое слово "BUFF_SIZE"
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdio.h>
    #include <time.h>

    #define ADD_DAYS  300
    #define BUFF_SIZE 40

    ////////////////////////////////////////////////////////////////////////////////
    int main()
    ////////////////////////////////////////////////////////////////////////////////
    {
    struct tm *u;
    char s1[BUFF_SIZE], s2[BUFF_SIZE];
    time_t timer, next;

    timer       = time(NULL);
    u           = localtime(&timer);
    strftime(s1, BUFF_SIZE, "%Y.%m.%d %H:%M:%S ", u);

    u->tm_mday += ADD_DAYS;
    next        = mktime(u);
    u           = localtime(&next);
    strftime(s2, BUFF_SIZE, "%Y.%m.%d %H:%M:%S ", u);

    printf("%s\n", s1);
    printf("%s\n", s2);
    //getchar();
    return 0;
    }

  • Доброго времени Елена. Подскажите пожалуйста, как получить метку времени UTC, в миллисекундах? 1583835726000 А затем конвертировать в wchar_t* const time_t timer = time(NULL); Умножение на 1000L, в VS почему то не срабатывает.

    • Кажется разобрался. Я не тот тип указывал в выводимой строке функции wprintf(); Для типа time_t применим %I64d, вместо %ld или %lu. Из за этого не корректно выводилось значение. Ну и конвертацию в wchar_t, выполняет функция _i64tow(timer, buf, 10);

  • Спасибо за ответ. Но я нашел в Интернете формулу расчета разности дат (спасибо опубликовавшему эту формулу). К сожалению, это формула, а не функция C++. Меня удивляет, что нет функции, т.к. по-моему, она должна быть довольно востребована (определение периода, возраста, средних величин за период и т.п.)...

  • Здравствуйте, ищу способ определения разницы в днях между двумя датами на C++ в Win32 GUI. Есть два поля DateTimePicker, вот и хочу знать разницу между ними. Думаю, что должна быть какая-то функция, но найти нигде не смог. Искал во многих форумах, везде объяснения для консольных программ. С помощью определения количества дней в годах и вычислении смог получить нужный результат для любых дат, но это заняло у меня примерно 140 строк. Функция difftime()дает какой-то странный, отличный от моего, результат, постоянный независимо от дат. Пишут, что получаются секунды, но не может быть в разнице в 6 лет около 10000 секунд. Можете помочь функцией, примером или ссылкой?

    • Елена Вставская
      Не приходилось работать с DateTimePicker в Win32 GUI на C++. Знаю только, как сделать в C#.

  • Здравствуйте, скажите, пожалуйста, что такое массив временных штампов? И как можно вывести каждый понедельник из этого массива, что он был четным днем недели?

  • Владимир
    спасибо,разберу ваш пример  и буду нормально оперировать данными. спасибо за оперативность.

  • Владимир
    добрый вечер,частенько захожу сюда чтобы разобраться лучше.. и все же.. у меня вопрос следующий. Есть дата, к которой нужно прибавить определенное (пользователем) количество дней и вывести новую дату на экран. Как реализовать этот алгоритм? Информации  на странице не достаточно. Не могли бы вы написать функции (и параметры этих функций) для решения моей задачи? Что использовать? У меня есть вариант организовать это все без time, но сами понимаете код там будет очень громоздкий...


  • Не подскажите а как получить доступ к дню недели? Мне надо что бы при понедельнике у меня значение принималось 1, при вторнике 2 и тд.

    • Елена Вставская
      Не поняла вопроса. В примере так и есть: понедельник - 1, вторник - 2.

      • как можно сделать вывод похожий на этот: cout<<(tm->tm_wday); Нужен только день недели без секунд часов и т.д.

        • Елена Вставская
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          #include <time.h>
          #include <iostream>
          int main()
          {
            const time_t SEC_IN_GOD = 31536000;
            using namespace std;
            const time_t timer = time(NULL);
            time_t t = timer - (SEC_IN_GOD * 47);

            cout << endl;
            cout << ((t / 60) / 60) % 24;
            cout << ":";
            cout << ((t / 60) % 60) / 10;
            cout << ((t / 60) % 60) % 10;
            cout << ":";
            cout << (t % 60) / 10;
            cout << (t % 60) % 10;

            getchar();
            return 0;
          }
          Формат %u выводит номер дня недели, %A - название.

        • И почему нижеприведенный код не правильно показывает время в часах? Влияние високосного дня должен же влиять только на дату, но не на время же
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          #include <time.h>
          #include <iostream>
          int main()
          {
            const time_t SEC_IN_GOD = 31536000;
            using namespace std;
            const time_t timer = time(NULL);
            time_t t = timer - (SEC_IN_GOD * 47);

            cout << endl;
            cout << ((t / 60) / 60) % 24;
            cout << ":";
            cout << ((t / 60) % 60) / 10;
            cout << ((t / 60) % 60) % 10;
            cout << ":";
            cout << (t % 60) / 10;
            cout << (t % 60) % 10;

            getchar();
            return 0;
          }

          • Елена Вставская
            Проблем не вижу. Время выводится для часового пояса GMT+0 корректно. Отличается от того, что на компьютере ровно на столько часов, сколько соответствуют часовому поясу.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *