Кафедра ИТКафедра ИТ
Обучение
  • О кафедре
  • Направления подготовки
  • Друзья и партнеры
  • Структура кафедры
  • Обращение к студентам
  • Официальный сайт «ВШП»
GitHub
Обучение
  • О кафедре
  • Направления подготовки
  • Друзья и партнеры
  • Структура кафедры
  • Обращение к студентам
  • Официальный сайт «ВШП»
  • ОП.04 - 13 - Особенности реализации встроенных функций даты и времени

Примечание

ЭТО АРХИВНАЯ ВЕРСИЯ КУРСА!

Материалы предназначаются для пересдающих дисциплину "ОП.04 - Основы алгоритмизации и программирования" в соответствии с учебными планами СПО годов набора ДО 2023-го.

Материалы были перенесены со старого сайта с минимальной доработкой, поэтому не все возможности курса могут работать как ожидается, где-то может слететь форматирование.

Домашние задания в рамках курса проверяться не будут!

ОП.04 - 13 - Особенности реализации встроенных функций даты и времени

Код примера для практической работы

Историческая справка

Вы когда-нибудь задумывались о том, как хранится в компьютере время? Включение и выключение компьютера никак не влияет на часы. Можно сделать вывод, что часы в компьютере работают сами по себе.

Это действительно так. Основные часы компьютера — аппаратные, они живут самостоятельной жизнью и имеют свою собственную батарею. При включении компьютер считывает данные этих часов, записывает к себе в память и начинает самостоятельно отсчитывать время. Эти часы называются системными. Любое изменение системных часов влияет и на аппаратные.

В большинстве современных операционных систем системное время представляется в формате Unix time. Оно определяется как количество секунд, прошедших с полуночи 1 января 1970 года. Время с этого момента называют «Началом эпохи Unix» или просто «Началом эпохи».

Unix-время (англ. Unix time, также POSIX-время) — система описания моментов во времени, принятая в Unix и других POSIX-совместимых операционных системах. Определяется как количество секунд, прошедших с полуночи (00:00:00 UTC) 1 января 1970 года (четверг); этот момент называют «эпохой Unix» (англ. Unix Epoch).

Unix-время представлено целым числом, которое увеличивается с каждой прошедшей секундой без необходимости вычислений для определения года, месяца, дня, часа или минуты для удобства восприятия человеком. Современное Unix-время согласуется со Всемирным координируемым временем (UTC) — отсчет происходит в секундах системы СИ.

Всемирное время или UT (англ. Universal Time) — шкала времени, основанная на вращении Земли. Всемирное время является современной заменой среднего времени по Гринвичу (GMT), которое сейчас иногда некорректно используется в качестве синонима для всемирного координированного времени (UTC).

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

Всемирное координированное время (англ. Coordinated Universal Time, UTC) — стандарт, по которому общество регулирует часы и время. Отличается на целое количество секунд от атомного времени и на дробное количество секунд от всемирного времени UT.

UTC было введено вместо устаревшего среднего времени по Гринвичу (GMT), поскольку шкала GMT является неравномерной и связана с суточным вращением Земли. В свою очередь, шкала UTC основана на равномерной шкале атомного времени (TAI) и является более удобной для гражданского использования. Время по UTC не переводится ни зимой, ни летом. Поэтому для тех мест, где есть переход на летнее время, меняется смещение относительно UTC. Часовые пояса вокруг земного шара выражаются как положительное или отрицательное смещение от UTC.

Вернемся к Unix-time. В момент времени 00:00:00 UTC 1 января 1970 года (четверг) Unix-время равно нулю. Начиная с этого времени, число возрастает на определённое количество в день. Временной промежуток одного дня почти всегда разбит на 86 400 секунд, но при объявлении дополнительных секунд составляет 86 401 секунду. Такие секунды, согласно Всемирному времени, сохраняют длительность дней синхронизированной со временем оборота планеты. В Unix-времени соответствующие номера секунд повторяются, то есть високосные секунды не учитываются. Таким образом, к примеру, 16 сентября 2004 года в 00:00:00, спустя 12677 дней после начала отсчета Unix-времени, время будет представлено числом 12 677 × 86 400 = 1 095 292 800, или в случае с 17 декабря 2003 года в 00:00:00, через 12403 дня после начала отсчёта время будет являться числом 12403 × 86 400 = 1 071 619 200. Расчеты могут быть также произведены в обратном направлении, используя отрицательные числа. К примеру, дата 4 октября 1957 года 00:00:00, а это 4472 дня до начала отсчета, представлена в Unix-времени числом −4472 × 86 400 = −386 380 800.

Каждый день число, представляющее Unix-время, вычисляется описанным образом в UTC (00:00:00Z), и увеличивается ровно на 1 в секунду, начиная с полночи. Используемую целочисленную систему удобно использовать для сравнения и хранения дат (дата и время в этом формате занимают всего 4 или 8 байт). При необходимости обращения к элементам дат (день, месяц, год) секунды можно преобразовать в любой подходящий формат (и наоборот).

В программах для хранения Unix-времени используется целочисленный знаковый тип. 32-битные числа со знаком могут ссылаться на моменты времени от пятницы 13 декабря 1901 года 20:45:52 до вторника 19 января 2038 года 03:14:07 включительно.

Минимальная дата в знаковом 32-битном представлении — 13 декабря 1901 года, 20:45:52 UTC (0x80000000, −2 147 483 648 секунд от 1 января 1970 года).

Главной критической датой с точки зрения Unix-времени считается 19 января 2038 года в 03:14:08 по всемирному времени, когда значение переменной, отсчитывающей число секунд, прошедших с 1 января 1970 года, достигнет 2312^{31}231, что может привести к ошибочной интерпретации этого числа как отрицательного. Комплекс рисков, связанных с этой датой, получил наименование проблемы 2038 года. Возможное решение данной проблемы состоит в использовании для хранения времени не 32-битной, а 64-битной переменной (что и делается во всех современных 64-битных операционных системах), этого хватит на 292 млрд лет.

Конкретная дата в формате Unix time называется timestamp (временной штамп).

Дата и время в JavaScript

Для представления даты и времени в языке JavaScript используется встроенный объект Date. Он содержит дату и время, а также предоставляет методы управления ими. Например, его можно использовать для хранения времени создания/изменения, для измерения времени или просто для вывода текущей даты.

Для создания нового объекта Date нужно вызвать конструктор new Date() с одним из следующих аргументов:

new Date()

Без аргументов — создать объект Date с текущими датой и временем:

let now = new Date();
console.log( now ); // показывает текущие дату и время

new Date(milliseconds)

Создать объект Date с временем, равным количеству миллисекунд (тысячная доля секунды), прошедших с 1 января 1970 года UTC+0.

// 0 соответствует 01.01.1970 UTC+0
let Jan01_1970 = new Date(0);
console.log( Jan01_1970 );

// теперь добавим 24 часа и получим 02.01.1970 UTC+0
let Jan02_1970 = new Date(24 * 3600 * 1000);
console.log( Jan02_1970 );

Целое число, представляющее собой количество миллисекунд, прошедших с начала 1970 года, называется таймстамп (англ. timestamp). Это — легковесное численное представление даты. Из таймстампа всегда можно получить дату с помощью new Date(timestamp) и преобразовать существующий объект Date в таймстамп, используя метод date.getTime().

Датам до 1 января 1970 будут соответствовать отрицательные таймстампы, например:

// 31 декабря 1969 года
let Dec31_1969 = new Date(-24 * 3600 * 1000);
console.log( Dec31_1969 );

new Date(datestring)

Если аргумент всего один, и это строка, то из неё «прочитывается» дата. Алгоритм разбора – такой же, как в Date.parse, который мы рассмотрим позже.

let date = new Date("2017-01-26");
console.log(date);
// Время не указано, поэтому оно ставится в полночь по Гринвичу и
// меняется в соответствии с часовым поясом места выполнения кода
// Так что в результате можно получить
// Thu Jan 26 2017 11:00:00 GMT+1100 (восточно-австралийское время)
// или
// Wed Jan 25 2017 16:00:00 GMT-0800 (тихоокеанское время)

new Date(year, month, date, hours, minutes, seconds, ms)

Создать объект Date с заданными компонентами в местном часовом поясе. Обязательны только первые два аргумента.

  • year должен состоять из четырёх цифр. Для совместимости также принимаются 2 цифры и рассматриваются как 19xx, к примеру, 98 здесь это тоже самое, что и 1998, но настоятельно рекомендуется всегда использовать 4 цифры.
  • month начинается с 0 (январь) по 11 (декабрь).
  • Параметр date здесь представляет собой день месяца. Если параметр не задан, то принимается значение 1.
  • Если параметры hours/minutes/seconds/ms отсутствуют, их значением становится 0.

Например:

let date1 = new Date(2011, 0, 1, 0, 0, 0, 0); // // 1 Jan 2011, 00:00:00
console.log( date1 );

let date2 = new Date(2011, 0, 1); // то же самое, так как часы и проч. равны 0
console.log( date2 );

Максимальная точность — 1 мс (до 1/1000 секунды):

let date = new Date(2011, 0, 1, 2, 3, 4, 567);
console.log( date ); // 1.01.2011, 02:03:04.567

Получение компонентов даты

Существуют методы получения года, месяца и т.д. из объекта Date:

  • getFullYear() — Получить год (4 цифры)
  • getMonth() — Получить месяц, от 0 до 11.
  • getDate() — Получить день месяца, от 1 до 31, что несколько противоречит названию метода.
  • getHours(), getMinutes(), getSeconds(), getMilliseconds() — Получить, соответственно, часы, минуты, секунды или миллисекунды.
  • getDay() — Вернуть день недели от 0 (воскресенье) до 6 (суббота). Несмотря на то, что в ряде стран за первый день недели принят понедельник, в JavaScript начало недели приходится на воскресенье.

[!WARNING]
Никакого getYear(). Только getFullYear()!

Многие интерпретаторы JavaScript реализуют нестандартный и устаревший метод getYear(), который порой возвращает год в виде двух цифр. Пожалуйста, обходите его стороной. Если нужно значение года, используйте getFullYear().

Все вышеперечисленные методы возвращают значения в соответствии с местным часовым поясом.

Однако существуют и их UTC-варианты, возвращающие день, месяц, год для временной зоны UTC+0: getUTCFullYear(), getUTCMonth(), getUTCDay(). Для их использования требуется после get подставить UTC.

Если ваш местный часовой пояс смещён относительно UTC, то следующий код покажет разные часы:

// текущая дата
let date = new Date();

// час в вашем текущем часовом поясе
console.log( date.getHours() );

// час в часовом поясе UTC+0 (лондонское время без перехода на летнее время)
console.log( date.getUTCHours() );

Помимо вышеприведённых методов, существуют два особых метода без UTC-варианта:

  • getTime() - Для заданной даты возвращает таймстамп — количество миллисекунд, прошедших с 1 января 1970 года UTC+0.

  • getTimezoneOffset() - Возвращает разницу в минутах между UTC и местным часовым поясом:

    // если вы в часовом поясе UTC-1, то выводится 60
    // если вы в часовом поясе UTC+3, выводится -180
    console.log( new Date().getTimezoneOffset() );
    

Установка компонентов даты

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

  • setFullYear(year, [month], [date])
  • setMonth(month, [date])
  • setDate(date)
  • setHours(hour, [min], [sec], [ms])
  • setMinutes(min, [sec], [ms])
  • setSeconds(sec, [ms])
  • setMilliseconds(ms)
  • setTime(milliseconds) (устанавливает дату в виде целого количества миллисекунд, прошедших с 01.01.1970 UTC)

У всех этих методов, кроме setTime(), есть UTC-вариант, например: setUTCHours().

Как мы видим, некоторые методы могут устанавливать сразу несколько компонентов даты, например: setHours(). Если какая-то компонента не указана, она не меняется.

Например:

let today = new Date();

today.setHours(0);
console.log(today); // выводится сегодняшняя дата, но значение часа будет 0

today.setHours(0, 0, 0, 0);
console.log(today); // всё ещё выводится сегодняшняя дата, но время будет ровно 00:00:00.

Автоисправление даты

Автоисправление — это очень полезная особенность объектов Date. Можно устанавливать компоненты даты вне обычного диапазона значений, а объект сам себя исправит.

Пример:

let date = new Date(2013, 0, 32); // 32 января 2013 ?!?
console.log(date); // ...1-е февраля 2013!

Неправильные компоненты даты автоматически распределяются по остальным.

Предположим, нам требуется увеличить дату «28 февраля 2016» на два дня. В зависимости от того, високосный это год или нет, результатом будет «2 марта» или «1 марта». Нам об этом думать не нужно. Просто прибавляем два дня. Объект Date позаботится об остальном:

let date = new Date(2016, 1, 28);
date.setDate(date.getDate() + 2);

console.log( date ); // 1 Mar 2016

Эту возможность часто используют, чтобы получить дату по прошествии заданного отрезка времени. Например, получим дату «спустя 70 секунд с текущего момента»:

let date = new Date();
date.setSeconds(date.getSeconds() + 70);

console.log( date ); // выводит правильную дату

Также можно установить нулевые или даже отрицательные значения. Например:

let date = new Date(2016, 0, 2); // 2 Jan 2016

date.setDate(1); // задать первое число месяца
console.log( date );

date.setDate(0); // первый день месяца -- это 1, так что выводится последнее число предыдущего месяца
console.log( date ); // 31 Dec 2015

Преобразование к числу, разность дат

Если объект Date преобразовать в число, то получим таймстамп по аналогии с date.getTime():

let date = new Date();
console.log(+date); // количество миллисекунд, то же самое, что date.getTime()

Важный побочный эффект: даты можно вычитать, в результате получаем разность в миллисекундах.

Этот приём можно использовать для измерения времени:

let start = new Date(); // начинаем отсчёт времени

// выполняем некоторые действия
for (let i = 0; i < 100000; i++) {
  let doSomething = i * i * i;
}

let end = new Date(); // заканчиваем отсчёт времени

console.log( `Цикл отработал за ${end - start} миллисекунд` );

Date.now()

Если нужно просто измерить время, объект Date нам не нужен.

Существует особый метод Date.now(), возвращающий текущую метку времени. Семантически он эквивалентен new Date().getTime(), однако метод не создаёт промежуточный объект Date. Так что этот способ работает быстрее и не требует лишней памяти. Данный метод используется из соображений удобства или когда важно быстродействие, например, при разработке игр на JavaScript или других специализированных приложений.

Вероятно, предыдущий пример лучше переписать так:

let start = Date.now(); // количество миллисекунд с 1 января 1970 года

// выполняем некоторые действия
for (let i = 0; i < 100000; i++) {
  let doSomething = i * i * i;
}

let end = Date.now(); // заканчиваем отсчёт времени

console.log( `Цикл отработал за ${end - start} миллисекунд` ); // вычитаются числа, а не даты

Разбор строки с датой

Метод Date.parse(str) считывает дату из строки.

Формат строки должен быть следующим: YYYY-MM-DDTHH:mm:ss.sssZ, где:

  • YYYY-MM-DD — это дата: год-месяц-день.
  • Символ T используется в качестве разделителя.
  • HH:mm:ss.sss — время: часы, минуты, секунды и миллисекунды.
  • Необязательная часть Z обозначает часовой пояс в формате +-hh:mm. Если указать просто букву Z, то получим UTC+0.

Возможны и более короткие варианты, например, YYYY-MM-DD или YYYY-MM, или даже YYYY.

Вызов Date.parse(str) обрабатывает строку в заданном формате и возвращает таймстамп (количество миллисекунд с 1 января 1970 года UTC+0). Если формат неправильный, возвращается NaN.

Например:

let ms = Date.parse('2012-01-26T13:51:50.417-07:00');

console.log(ms); // 1327611110417 (таймстамп)

Можно тут же создать объект new Date из таймстампа:

let date = new Date( Date.parse('2012-01-26T13:51:50.417-07:00') );

console.log(date);

Что почитать по теме

  • Статья на Википедии - Всемирное время
  • Статья на Википедии - Всемирное координированное время
  • Статья на Википедии - Unix-время
  • Современный учебник JavaScript - Дата и время
  • W3Schools - JavaScript Date Objects
  • W3Schools - JavaScript Date Formats
  • W3Schools - JavaScript Get Date Methods
  • W3Schools - JavaScript Set Date Methods
Последнее обновление: 31.10.2025, 18:45
Предыдущая
ОП.04 - 12 - Функции и аргументы. Область видимости и контекст выполнения. Понятие рекурсии
Следующая
ОП.04 - 14 - Порядок выполнения и прерывания. Виды ошибок в программировании и способы отладки
© Кафедра информационных технологий ЧУВО «ВШП», 2025. Версия: 0.20.1
Материалы доступны в соответствии с лицензией: