Глаза страшат, а руки делают

ЧАСТЬ ВТОРАЯ


23. Объект Date
Содержание и методы объекта

  • устройство объекта Date;
  • создание объекта Date;
  • группа методов to...;
  • группа методов get...;
  • группа методов set...;
  • статические методы parse() и UTC().

Устройство объекта Date

Объект Date манипулирует датами и временем. В основе всех операций, связанных с этим объектом, лежат текущие системные дата и время, установленные на компьютере пользователя.

Наши скрипты работают на web-страницах, которые можно открыть в любой точке планеты.

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

Все эти тонкости приходится учитывать при работе с объектом Date.

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

Базовое время, своего рода «временная ось» объекта приходится на 1 января 1970 года, 0 часов, 0 минут по Гринвичскому меридиану.

Время отсчитывается в миллисекундах в обе стороны от этой оси (соответственно в отрицательном и положительном значении). Но это всё происходит «за кулисами», для вывода времени на экран используются механизмы, приводящие его в естественный и понятный для нас вид. «Мотор» этих механизмов менялся в разных версиях языка; этого мы тоже коснёмся, когда будем говорить о конкретной работе методов.

«Запас прочности» — по 864×1013 миллисекунд (по 100 млн. дней или примерно по 285616 лет) в каждую сторону от оси.

Одна из неприятных и запутанных проблем заключается в том, что сам объект не содержит всевозможных «вторников», «апрелей», дат, часов, минут и секунд. Примитивным, то есть изначальным, данным по умолчанию значением объекта Date является количество миллисекунд от «оси отсчёта» до текущего показания системного таймера компьютера.

Строка с числом, месяцем, временем и т.д., которую мы видим при выводе значения объекта, — результат «невидимой» работы интерпретатора в браузере. Из-за того, что в разных браузерах интерпретаторы могут работать по-разному, возникают разночтения в формате вывода по умолчанию.

GMT и UTC

Эти термины встретятся нам и в названиях методов, и в полной строке формата объекта Date.

GMT — аббревиатура, означающая Greenwich Mean Time, основное время по Гринвичу.

UTC расшифровывается как Universal Time Coordinated, «Универсальное координированное время».

UTC — это новый эталон времени, базирующийся на GMT. Стандарт GMT считается устаревшим, хотя всё ещё употребляется. Практически, разница только в названии.

Все компьютеры отсчитывают время в UTC (GMT). Местное время, которое мы видим на компьютерных часах, — это поправка, введённая при настройке операционной системы. Поскольку объект Date работает именно с системным временем, он тоже учитывает эту поправку (хотя может и не учитывать — это уж как мы его запрограммируем).

Браузеры внутри себя сохраняют дату как значение миллисекунд в UTC (или GMT). Когда мы запрашиваем текущее время, браузер автоматически преобразовывает значение миллисекунд (в соответствии с зоной местного времени, основанной на установке клиентского компьютера) в часы и часовой пояс.

Создание объекта Date

Объект Date создается с помощью выражения:

var переменная = new Date([аргументы])

Если в конструкторе аргументы отсутствуют, то значением объекта будет текущая дата:

var myDate = new Date()

Обратите внимание

В любом случае после объекта ставятся круглые скобки.

Синтаксис объекта Date может выглядеть как строка или массив. Но мы уже знаем, что его «внутреннее» значение целочисленное. Однако, в отличие от числового объекта, он имеет встроенные «невидимые» функции, с помощью которых интерпретатор браузера создаёт подобие строки или массива. С этой строкой или массивом можно работать именно как со строкой или массивом, что мы увидим в дальнейшем. Но тут нужно быть осторожными, учитывая неоднородность интерпретаций браузеров.

Если мы хотим вывести заданную дату, то аргументами конструктора могут быть следующие строки:

var myDate = new Date("Месяц дд, гггг чч:мм:сс") // строка
var myDate = new Date("Месяц дд, гггг") // строка
var myDate = new Date(гггг, мм, дд, чч, мм, сс) // массив чисел
var myDate = new Date(гг, мм, дд, чч, мм, сс) // массив чисел
var myDate = new Date(гг, мм, дд) // массив чисел
var myDate = new Date(гггг, мм, дд) // массив чисел
var myDate = new Date(миллисекунды) // целое число

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

Месяц — полное либо сокращённое до 3 первых букв английское название месяца (без учёта регистра)

дд — дата в виде двухзначного (или однозначного) числа; если дата однозначна, то ставить перед числом 0 не обязательно.

гггг — полное написание года четырёхзначным числом.

гг — год в виде двух последних цифр.

чч:мм:сс — часы, минуты, секунды.

мм — после года — месяц в виде двухзначного.

Внимание!

Отсчёт месяцев начинается с нуля: 0 — январь, 11 — декабрь.

чч — часы в виде двухзначного (или однозначного) числа.

мм — после чч — минуты в виде двухзначного (или однозначного) числа.

сс — секунды в виде двухзначного (или однозначного) числа.

миллисекунды — количество миллисекунд, прошедших от начала указанной в объекте даты (если дата не указана, то от начала текущей даты).

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

Примитивный объект Date

Рассмотрим, какие же данные выводит примитивный объект Date.

Примечание

В разных браузерах формат данных немного различен.

var today = new Date();
document.write(today);

Результат в Вашем браузере

Теперь возьмём какую-нибудь фиксированную дату, например, 16 мая 2008 (когда я пишу этот урок), и посмотрим, как это выглядит в некоторых браузерах (время я не указываю, поэтому будет 0 часов, 0 минут, 0 секунд):

IE 6

Fri May 16 00:00:00 UTC+0400 2008

Mozilla 1-7-7

Fri May 16 2008 00:00:00 GMT+0400

Opera 8

Fri, 16 May 2008 00:00:00 GMT+0400

Ваш браузер

Fri, как Вы уже, наверно, догадались, означает сокращённый до 3 букв день недели (англ. Ftiday — пятница). UTC+0400 или GMT+0400 указывает на часовой пояс (стандартное время+ччмм). Этот показатель указывает часовой пояс клиентского компьютера, так что если Вы находитесь в другом поясе, то в графе «Ваш браузер» будет другой показатель.

Группы методов to..., get... и set...

Как выводить на экран не все данные объекта, а только нужные в данной ситуации (только время, только дату и т.п.)?

Как регулировать формат вывода (месяц.число или число.месяц)?

Как отображать месяц или день недели по-русски? по-немецки? по хинди?

Для этого у объекта Date есть много методов. Нужных, ненужных и просто лишних (ИМХО).

Беда в том, что многие методы выдают разные форматы в разных браузерах, в разных версиях браузеров, в разных операционных системах. Единственная возможность обойти эту проблему — брать из объекта только безусловные значения, а форму вывода программировать «руками». Такие скрипты получаются чуть длиннее, работа над ними чуть кропотливее, но они надёжны и предсказуемы.

Группа методов to...

Эти методы, начинающиеся с префикса to, задуманы для вывода отдельных элементов объекта Date и/или форматирования строки с учётом национальных настроек. Однако результат каждого метода хоть чем-нибудь, хоть одной запятой, но различается в разных браузерах.

Синтаксис

объект.имяМетода()

объект — обычно переменная, на которую назначен созданный конструктором новый объект Date.

toDateString() — выводит только дату (без времени).

toGMTString() — выводит полный набор данных объекта Date без учёта часового пояса (идентичен методу toUTCString()).

toLocaleDateString() — теоретически, выводит дату в национальном формате; практически, делает это только в IE.

toLocaleString() — та же петрушка с полным форматом объекта.

toLocaleTimeString() — в браузерах IE 5+ и Opera 9+ отображает однозначные значения часов без нуля впереди, в браузере Mozilla просто не выводит показатель GMT/UTC, в отличие от toTimeString().

toTimeString() — выводит время + показатель GMT/UTC.

toUTCString() — идентичен методу toGMTString()

Вот как это всё выглядит в следующих браузерах под Windows XP:

Метод

Internet Explorer 6

Mozilla 1-7-7

Opera 8

toDateString()

Sat May 17 2008

Sat May 17 2008

Sat, 17 May 2008

toGMTString()

Fri, 16 May 2008 21:37:10 UTC

Fri, 16 May 2008 21:37:10 GMT

Fri, 16 May 2008 21:37:10 GMT

toLocaleDateString()

17 мая 2008 г.

Saturday, May 17, 2008

17.05.2008

toLocaleString()

17 мая 2008 г. 1:37:10

Saturday, May 17, 2008 01:37:10

17.05.2008 1:37:10

toLocaleTimeString()

1:37:10

01:37:10

1:37:10

toTimeString()

01:37:10 UTC+0400

01:37:10 GMT+0400

01:37:10 GMT+0400

toUTCString()

Fri, 16 May 2008 21:37:10 UTC

Fri, 16 May 2008 21:37:10 GMT

Fri, 16 May 2008 21:37:10 GMT

Эти методы не позволяют редактировать заданный формат по-своему. Для того, чтобы вручную манипулировать форматами по собственному усмотрению, нужно вывести необходимые данные одним из методов группы get...

К группе методов to... можно отнести и метод toString(), применяемый ко всем встроенным объектам, содержащим данные. Подробнее об этом методе будет сказано при рассмотрении объекта Object.

Группа методов get...

Каждый из методов с префиксом get возвращает отдельные параметры объекта Date.

Синтаксис

объект.имяМетода()

объект — обычно переменная, на которую назначен созданный конструктором новый объект Date.

Давайте создадим контрольный объект Date с фиксированным временем (для чистоты и ясности эксперимента) и посмотрим, что возвращают эти методы.

var controlDate = new Date("May, 17, 2008, 2:33:10")
var sMSeconds = controlDate.setMilliseconds(236)

Во второй переменной мы настраиваем фиксированные миллисекунды с помощью соответствующего метода группы set... (см. ниже)

Теперь создадим переменные для вывода на экран результатов каждого из методов. Хотя это не обязательно, можно выводить просто document.write(controlDate.имяМетода()).

var gDate = controlDate.getDate()
var gDay = controlDate.getDay()
var gFullYear = controlDate.getFullYear()
var gHours = controlDate.getHours()
var gMilliseconds = controlDate.getMilliseconds()
var gMinutes = controlDate.getMinutes()
var gMonth = controlDate.getMonth()
var gSeconds = controlDate.getSeconds()
var gTime = controlDate.getTime()
var gTimezoneOffset = controlDate.getTimezoneOffset()
var gUTCDate = controlDate.getUTCDate()
var gUTCDay = controlDate.getUTCDay()
var gUTCFullYear = controlDate.getUTCFullYear()
var gUTCHours = controlDate.getUTCHours()
var gUTCMilliseconds = controlDate.getUTCMilliseconds()
var gUTCMinutes = controlDate.getUTCMinutes()
var gUTCMonth = controlDate.getUTCMonth()
var gUTCSeconds = controlDate.getUTCSeconds()

Результаты следующих методов одинаковы во всех браузерах:

Метод

Описание

Результат работы

getDate()

Возвращает число месяца

getDay()

Возвращает числовое значение дня недели (нумерация начинается с нуля, стартовый нулевой день недели — воскресенье).

Не имеет обратного метода setDay

getFullYear()

Возвращает полное четырёхзначное значение года. Не требует поправки для года после 1999.

getHours()

Возвращает значение часа (в формате от 0 до 24).

getMilliseconds()

Возвращает миллисекунды, прошедшие от наступления последней секунды.

getMinutes()

Возвращает значение минут.

getMonth()

Возвращает числовое значение месяца (от 0 до 11)

getSeconds()

Возвращает значение секунд

getTime()

Возвращает количество миллисекунд, прошедших от 1.01.1970 0 ч. 0 м. 0 с. до времени, определённом в текущем объекте Date.

getTimezoneOffset()

Возвращает разницу между GMT/UTC и местным временем (в минутах).

Не имеет обратного метода setTimezoneOffset()

getUTCDate()

То же, что getDate(), но в значении GMT/UTC.

getUTCDay()

То же, что getDay(), но в значении GMT/UTC.

Не имеет обратного метода setUTCDay

getUTCFullYear()

То же, что getFullYear(), но в значении GMT/UTC.

getUTCHours()

То же, что getHours(), но в значении GMT/UTC.

getUTCMilliseconds()

То же, что getMilliseconds(), но в значении GMT/UTC.

getUTCMinutes()

То же, что getMinutes(), но в значении GMT/UTC.

getUTCMonth()

То же, что getMonth(), но в значении GMT/UTC.

getUTCSeconds()

То же, что getSeconds(), но в значении GMT/UTC.

Эти два метода правильно работают только в IE. У них есть универсальная альтернатива, поэтому можно просто о них забыть.

Метод

Описание

Результат работы

IE

Остальные браузеры

getVarDate()

Преобразует примитивное значение объекта Date в формат VT_DATE и возвращает его. Результат зависит от региональных настроек и не используется JavaScript. Поэтому этот метод предназначен исключительно для взаимодействия с COM-объектами, объектами ActiveX или с языками, которые используют формат даты VT_DATE (таковы, например, Visual Basic и VBScript).

В IE возвращает то же, что и объект Date без аргументов. В других браузерах оставляет пустой экран, убирая всё остальное.

Не имеет обратного метода setVarDate()

Sat May 17 02:33:10 UTC+0400 2008

Пустой экран

getYear()

Возвращает число лет с 1900 года. Корректно работает в диапазоне 1900–1999

Справа примеры для 1885, 1985 и 2085 годов.

1885

85

2085

-15

85

185

Группа методов set...

Это методы, парные методам get... (кроме методов getDay, getTimezoneOffset, getUTCDay и getVarDate). С их помощью можно назначать на объект Date различные его компоненты.

Внимание!

Эти методы изменяют исходный объект! После их использования, чтобы создать «чистый» объект Date, нужно снова воспользоваться конструктором и назначить новый объект Date на новую переменную.

Как правило, большинство компонентов можно назначить прямо в конструкторе, обходясь без этих методов. Но в конструкторе, например, нельзя назначить миллисекунды. В предыдущем примере для назначения фиксированных миллисекунд мне пришлось воспользоваться методом setMilliseconds().

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

var currentDate = new Date()
var beforeLastDate = new Date()
beforeLastDate.setDate(currentDate.getDate() - 2) 
document.write("I объект Date: " + currentDate + "<br>")
document.write("II объект Date: " + beforeLastDate)

Результат

Каждый метод set... должен иметь один обязательный аргумент (а некоторые могут иметь несколько необязательных дополнительных аргументов). Аргументами этих методов служат числовые значения, которые интерпретируются как составляющие объекта Date, соответствующие значениям параллельного метода get... Если параметр аргумента не соответствует диапазону значений (например, объект.setDate(0) или объект.setDate(33), тогда как минимальное значение даты — 1, а максимальное — 31, да и то не для каждого месяца), то метод всё равно сработает.

Как работают электронные часы и календари? Когда меньшее значение проходит свой порог, следующее за ним большее автоматически переключается. После 59-й секунды прибавляется минута, после 30-го числа апрель, допустим, сменится на май, а май на июнь, соответственно, после 31-го, и т.д.

Если у нас значение setDate() назначено на 0, а месяц объекта — октябрь, то объект Date станет равен «0 октября», то есть «1 октября - 1», то есть «30 сентября».

Точно так же «31 июня» интерпретируется как «30 июня + 1», то есть «1 июля».

Пройдёмся по основным и дополнительным аргументам методов группы set... (дополнительные, как всегда, обозначены в квадратных скобках).

Метод

Аргументы

setDate()

дата

setFullYear()

год[, месяц, дата]

setHours()

часы[, минуты, секунды, миллисекунды]

setMilliseconds()

миллисекунды (отсчёт с начала текущей секунды объекта Date).

setMinutes()

минуты[, секунды, миллисекунды]

setMonth()

месяц[, дата]

setSeconds()

секунды[, миллисекунды]

setTime()

миллисекунды (отсчёт с первой секунды 1 января 1970 г.)

setUTCDate()

Те же, что и у setDate(), но в значении GMT/UTC.

setUTCFullYear()

Те же, что и у setFullYear(), но в значении GMT/UTC.

setUTCHours()

Те же, что и у setHours(), но в значении GMT/UTC.

setUTCMilliseconds()

Те же, что и у setMilliseconds(), но в значении GMT/UTC.

setUTCMinutes()

Те же, что и у setMinutes(), но в значении GMT/UTC.

setUTCMonth()

Те же, что и у setMonth(), но в значении GMT/UTC.

setUTCSeconds()

Те же, что и у setSeconds(), но в значении GMT/UTC.

setYear()

год

Метод setYear() работает забавно. При параметрах от 0 до 99 возвращает 1900–1999. При параметрах от 100 возвращает заданное число. При отрицательных параметрах везде, кроме IE, возвращает заданное число, а в IE — параметр - 1 + "B.C.".

То есть, при параметре -1 возвратится «2 B.C.», при параметре -645 — «646 B.C.» и т.д.

B.C. означает before Christ, т.е. до н.э.

Получить 1 г. до н.э. этим методом невозможно, так как 0 — это 1900. Но нулевой параметр метода setFullYear даст нам «1 B.C.» (только в IE).

В общем, чтобы задать год до нашей эры, его абсолютное значение должно быть на единицу меньше, чем желаемый результат. Но предполагаю, что настраивать объект Date на столь отдалённые времена нам если и потребуется вообще, то один-два раза в жизни.

Статические методы объекта Date

Помимо этих методов, есть у объекта Date методы parse() и UTC().

Это так называемые статические методы, они применяются непосредственно к объекту Date, а не к его экземплярам, созданным нами.

То есть:

var myDate = new Date();  // создание экземпляра
var strDate = "Jan 17, 2008"
var pTime = myDate.parse(strDate)  // применение к экземпляру: ошибка
var pTime = Date.parse(strDate)    // применение к объекту: верно

Ещё раз напомню, ч то собственно объект уже существует в ядре JavaScript, мы же создаём лишь его новые экземпляры. Статические методы, в отличие от остальных, работают не с экземплярами, а с самим объектом (см. урок 18).

Мне эти два метода пока ни разу не пригодились. То, что они делают, можно выполнить с помощью тех методов, которые мы уже рассмотрели, — и, на мой взгляд, гораздо проще и яснее.

Привожу их только для того, чтобы ликвидировать дыру в Вашем самообразовании; чтобы, столкнувшись с ними, Вы не оказались в положении барана у новых ворот.

Метод parse()

Преобразует строковый эквивалент даты в количество миллисекунд, прошедших с 1 января 1970.

«Строковый эквивалент» означает, что аргументом метода должен быть тип данных String (не путайте с объектом String).

Возвращает количество миллисекунд, прошедшее от 1 января 1970 год, 00:00:00 до указанной даты (по местному времени). Используется для установки значений даты на базе строковых значений.

Синтаксис

Date.parse(строка_даты)

Аргумент

строка_даты — строковый тип данных, представляющий значение времени.

Примеры допустимых значений

"Jan 17, 2008"

"Mon, 25 Dec 1995 13:30:00 GMT"

"Tue Mar 25 00:00:00 UTC+0300 2003"

А также результаты методов toString() (с объектом Date), toGMTString(), toUTCString(), toLocaleString().

Метод UTC()

Возвращает количество миллисекунд, прошедшее от 1 января 1970 года, 00:00:00 до указанной даты (по Гринвичскому времени). В отличие от аргументов для конструктора объекта Date, параметры аргументов для метода UTC() должны быть в UTC времени. Этот метод не генерирует объект даты, как это делает конструктор объекта Date.

Синтаксис

Date.UTC(гггг, мм, дд[, чч, мм, сс, мс])

Аргументы

гггг — полное написание года четырёхзначным числом.

мм — после года — месяц (отсчёт с нуля).

дд — дата.

чч — часы.

мм — после чч — минуты.

сс — секунды.

мс — количество миллисекунд, прошедших от начала указанной секунды.

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

Однако, простого использования этих методов недостаточно для всестороннеё работы с объектом. О некоторых способах работы и даже о создании дополнительных методов мы поговорим на следующем уроке.


Итак, мы узнали:

как работать со стандартными методами объекта Date.


К следующему уроку >>


 009189