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

ЧАСТЬ ВТОРАЯ


24. Объект Date
Способы работы с объектом

  • создание собственных форматов даты;
  • использование массивов;
  • пополняем библиотечку собственных методов;
  • методы setInterval() и setTimeout() объекта Window;
  • генерирование случайных чисел с помощью объекта Date.

Создание собственных форматов даты

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

Это можно делать с помощью настройки аргументов методов группы get..., а можно — с помощью свойства prototype. Это свойство есть у всех встроенных объектов, и разъяснено оно будет в уроке об объекте Object, но некоторые способы его использования мы рассмотрим уже сегодня.

Работа с массивами данных

Давайте запрограммируем вывод сегодняшнего числа вот в таком формате:

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

var months = [" января ", " февраля ", " марта ", " апреля ", " мая ", " июня ", " июля ", " августа ", " сентября ", " октября ", " ноября ", " декабря "];
var days = ["Воскресенье, ", "Понедельник, ", "Вторник, ", "Среда, ", "Четверг, ", "Пятница, ", "Суббота, "];

Создадим экземпляр Date.

var now = new Date();

Индексы наших массивов соответствуют возвращающим значениям методов getDay() и getMonth(). Поэтому выражения days[now.getDay()] и months[now.getMonth()] возвратят день недели и месяц в нашем формате.

Теперь можно формировать всё выражение:

var nowFullDate = days[now.getDay()] + now.getDate() + months[now.getMonth()] + now.getFullYear + " года";

Проверяем:

document.write(nowFullDate);

Результат мы уже видели выше.

Вот ещё один вариант массива, разберитесь в нём сами.

var romanMonths = ["/I-", "/II-", "/III-", "/IV-", "/V-", "/VI-", "/VII-", "/VIII- ", "/IX-", "/X-", "/XI-", "/XII-"];
var abbrYear = now.getFullYear().toString(10).substr(2, 2);
var abbrFullDate = now.getDate() + romanMonths[now.getMonth()] + abbrYear;
document.write(abbrFullDate);

Результат:

Примечание 1

В этом скрипте я пользуюсь переменной now экземпляра Date, уже созданного ранее. Чтобы использовать этот скрипт «с нуля», Вы должны сначала объявить переменную now как new Date().

Примечание 2

Как я уже говорил, метод getYear(), представляющий две последние цифры года, после 2000 в большинстве браузеров работает некорректно. Иногда разработчики добавляют «ветку» для дополнительного вычисления значений, больших чем 2000. В этом скрипте я «химически» вывожу двухзначную подстроку из метода getFullYear(). Это везде будет работать правильно. И никаких лишних условных операторов.

Создадим свой метод

В 21 уроке мы начали баловаться созданием собственных методов. Продолжим. Запакуем в метод вывод даты по-русски.

Date.prototype.getFullDate = getFullDate;
function getFullDate() {
// код функции
}

Заполняем.

1. Вставим в функцию наши массивы:

function getFullDate() {
var
months = [" января ", " февраля ", " марта ", " апреля ", " мая ", " июня ", " июля ", " августа ", " сентября ", " октября ", " ноября ", " декабря "];
var days = ["Воскресенье, ", "Понедельник, ", "Вторник, ", "Среда, ", "Четверг, ", "Пятница, ", "Суббота, "];
// ...
// ...

}

2. Воспользуемся следующим выражением:

var n = days[this.getDay()] + this.getDate() + months[this.getMonth()] + this.getFullYear() + " года";
return n;

Напоминаю, что ключевым словом this инициализируются значения функции, а ключевое слово return указывает, что именно она возвращает (в данном случае — локальную переменную n).

Целиком:

function getFullDate() {
var
months = [" января ", " февраля ", " марта ", " апреля ", " мая ", " июня ", " июля ", " августа ", " сентября ", " октября ", " ноября ", " декабря "];
var days = ["Воскресенье, ", "Понедельник, ", "Вторник, ", "Среда, ", "Четверг, ", "Пятница, ", "Суббота, "];
var n = days[this.getDay()] + this.getDate() + months[this.getMonth()] + this.getFullYear() + " года";
return n;
}

Теперь попробуем вызвать новый метод:

var testDate = new Date();
document.write(testDate.getFullDate());

Результат:

Итак, в нашей маленькой библиотечке ещё один метод.

Методы объекта Window для работы с временем

Все данные текущей даты/времени, которые мы выводили, генерировались во время открытия страницы и застывали в этой позиции. Обновить данные можно только обновив страницу. А как сделать часики, которые постоянно показывали бы точное время?

Для этого можно воспользоваться методами объекта Window setInterval() или setTimeout()

Метод setInterval()

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

Синтаксис

(Упоминание объекта Window, как мы помним, необязательно.)

setInterval("функция()", интервал)

или

var имя_переменной = setInterval("функция()", интервал)

Назначение на глобальную переменную может оказаться удобным, если понадобится код для отмены метода.

Аргументы

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

интервал — интервал обновления в миллисекундах.

Примечания

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

У метода есть ещё и третий, необязательный аргумент. Но разные браузеры отличаются в его использовании. В браузерах Netscape и Mozilla мы можем поместить в него аргументы вызываемой функции (в общих кавычках, через запятые). А в IE мы можем дополнительно указать язык скрипта (например, если мы берём функцию из VBScript).

А сейчас мы создадим простые электронные часики с форматом вывода чч:мм:сс.

1. Объявляем функцию.

Обратите внимание на аргумент place, его роль я объясню чуть позже.

function setClock(place) {

2. Внутри функции создаём экземпляр объекта Date — «контейнер» для нужных параметров.

Сразу объявим переменные, выводящие эти параметры.

var container = new Date()
var hh = container.getHours()
var mm = container.getMinutes()
var ss = container.getSeconds()

3. Однозначные параметры выводятся без префиксных нулей. А в электронных часах эти нули нужны. Значит, запрограммируем и их.

if (hh < 10) {hh = "0" + hh}
if (mm < 10) {mm = "0" + mm}
if (ss < 10) {ss = "0" + ss}

4. Объявляем переменную для вывода значений таймера.

var myTimer = hh + ":" + mm + ":" + ss

5.  Обеспечиваем вывод значений на экран.

Вот и пришла очередь для таинственного аргумента place. Поскольку функция не будет вызываться из HTML-кода, а будет переадресована в метод setInterval(), мы должны обеспечить в самой функции точное место, в котором будет отображаться таймер. Для этого вспомним метод document.getElementById() и свойство innerHTML. Это свойство задаёт или возвращает строку с содержанием того тэга, к которому обращено.

Можно, конечно, просто указать в функции конкретный ID, а потом присвоить его нужному тэгу HTML, но тогда функция потеряет свою универсальность. Каждый раз её придётся «точить» под конкретные обстоятельства.

Вот для этого и place.

document.getElementById(place).innerHTML = myTimer
}

На этой инструкции функция закончилась, и мы поставили закрывающую скобку.

Теперь осталось использовать метод setInterval(). В этом методе мы вызовем нашу функцию с конкретным ID в качестве аргумента (обратите внимание на кавычки в кавычках: внешние и вложенные кавычки должны быть разными).

setInterval("setClock('showTimer')", 1000)

Вот полный код скрипта:

<script type="text/javascript">
<!--
function setClock(place) {
var container = new Date()
var hh = container.getHours()
var mm = container.getMinutes()
var ss = container.getSeconds()
if (hh < 10) {hh = "0" + hh}
if (mm < 10) {mm = "0" + mm}
if (ss < 10) {ss = "0" + ss}
var myTimer = hh + ":" + mm + ":" + ss
document.getElementById(place).innerHTML = myTimer
}
setInterval("setClock('showTimer')", 1000)
// -->
</script>

Теперь осталось создать в коде HTML пустой тэг с указанным ID:

<h3 align="center" id="showTimer"></h3>

И вот что получилось:

Помните, в 19 уроке был такой заголовок:

Казнить  нельзя, помиловать

Это тоже сделано методом setInterval().

Вот этот код. Думаю, теперь Вы без труда разберётесь в нём сами. Поскольку эта функция не универсальная, а, так сказать, «на случай», я не стал заморачиваться с аргументом.

<script type="text/javascript">
<!--
function setMig() {
if
(document.getElementById("mig1").innerHTML == "," && document.getElementById("mig2").innerHTML == "&nbsp;")
{document.getElementById("mig1").innerHTML = "&nbsp;"
document.getElementById("mig2").innerHTML = ","}
else
{
document.getElementById("mig1").innerHTML = ","
document.getElementById("mig2").innerHTML = "&nbsp;"}
}

setInterval("setMig()", 700)
// -->
</script>

<p>Казнить<span id="mig1">&nbsp;</span> нельзя<span id="mig2">,</span> помиловать</p>

На оригинальной странице интервал был 1000. Здесь я специально его уменьшил, чтобы продемонстрировать одновременную работу скриптов с разными интервалами на одной странице.

Метод clearInterval()

Используется для отмены метода setInterval().

Синтаксис

clearInterval(значение)

Аргумент

значение — либо первый аргумент метода setInterval(), либо имя переменной, на которую был назначен setInterval().

Примечание

Чаще всего используется в событийных атрибутах HTML-тэгов (например, кнопки). Поскольку значения атрибутов сами по себе помещаются в кавычки, то при использовании первого аргумента метода setInterval() возникает неизбежность вложенных кавычек. Если же, как в нашем случае, аргумент уже имел вложенные кавычки, то для использования clearInterval() необходимо предварительно назначить setInterval() на переменную.

Вместо этого кода

setInterval("setClock('showTimer')", 1000)

нужно записать, например:

var stop = setInterval("setClock('showTimer')", 1000)

Тогда в HTML-коде мы можем создать, например, следующее:

<form>
<input type=
"button" value="стоп" onClick="clearInterval(stop)">
</form>

Нажатие этой кнопки остановит таймер.

Метод setTimeout()

Запускает одноразовый таймер, который вызывает выражение после задержки на указанный в аргументе интервал. Не мешает параллельной работе других скриптов. Полезен для действий, нуждающихся в задержке (например, в выпадающем меню бывает необходима некоторая задержка скрытия выпадающего блока, а то можно не успеть перенести на него мышку).

Синтаксис

setTimeout("функция()", интервал)

или

var имя_переменной = setTimeout("функция()", интервал)

Аргументы

"функция()" — имя функции, вызываемой этим методом (как и в методе setInterval(),имя функции принимается в виде строки и тоже должно быть в кавычках).

интервал — интервал обновления в миллисекундах.

Примечания

В качестве первого аргумента может быть не только функция, но и другое выражение, содержащее код выполняемой операции.

Третий, необязательный аргумент метода работает так же, как и в методе setInterval().

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

Понятно?

Скажем, наш таймер можно было бы изобразить так:

function setClock(place) {
var container = new Date()
var hh = container.getHours()
var mm = container.getMinutes()
var ss = container.getSeconds()
if (hh < 10) {hh = "0" + hh}
if (mm < 10) {mm = "0" + mm}
if (ss < 10) {ss = "0" + ss}
var myTimer = hh + ":" + mm + ":" + ss
document.getElementById(place).innerHTML = myTimer
setTimeout("setClock('showTimer')", 1000)
}

Функции JavaScript вызываются либо при открытии страницы, либо при возникновении события, на которое они назначены. Поэтому, чтобы такая функция заработала, нам потребуется добавить событие в тэг <body>:

<body onLoad="setClock('showTimer');">

А кроме того, придётся указать ID конкретного тэга в самой функции и в событии onLoad тэга <body>, и она утратит свою универсальность.

А также в некоторых случаях (не всегда предсказуемых заранее) подобная рекурсия может вызвать переполнение стека, следствием которого будет зависание системы (аналогично «зацикливанию» через оператор continue).

Отсюда напрашивается вывод: лучше, всё-таки, стараться использовать методы по их прямому назначению.

Метод clearTimeout()

Используется для отмены метода setTimeout().

Синтаксис

clearTimeout(значение)

Аргумент

значение — либо первый аргумент метода setTimeout(), либо имя переменной, на которую был назначен setTimeout().

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

Что означает сей странный заголовок?..

А ну-ка обновите страницу.

И ещё...

И ещё...

А, понятно: какой-то очередной фокус JavaScript. А какое отношение он имеет к объекту Date?

Да самое прямое!

?..

Все фразы, которые случайно выпадают в заголовок, являются элементами массива. А генерируется случайное число из... текущих секунд. Вот весь код:

var mots = new Array();
mots[0]="Грузите апельсины бочками. Братья Карамазовы.";
mots[1]="Графиня изменившимся лицом бежит пруду.";
mots[2]="Ударим автопробегом по бездорожью и разгильдяйству.";
mots[3]="Утром — деньги, вечером — стулья.";
mots[4]="Командовать парадом буду я.";
var num = now.getSeconds() % mots.length;
document.write("<h3 align='center'>" + mots[num] + "</h3>");

Видимо, особого объяснения требует следующая строка:

var num = now.getSeconds() % mots.length;

Оператор %, если помните, возвращает остаток от деления (если делимое меньше делителя, то возвращается делимое). Остаток всегда будет меньше делителя и выпадает на любое значение от 0 (деление без остатка) до делителя-1, то есть в нашем условии, когда делитель равен mots.length, остаток может выпасть на любой из индексов массива mots. Делим количество текущих секунд на размерность массива — и получаем какой-нибудь из его индексов.

Посмотрим, как это выглядит в динамике, с методом setInterval(). Для этого напишем функцию. Фразы из глобального массива мы присвоим локальной переменной (var myTxt = mots), а также создадим новый, локальный экземпляр Date: не хочет функция с «чужаками» работать.

Помещаю также и кнопку для остановки метода.

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

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

<script type="text/javascript">
<!--
function showTxt(place) {
var tiktak = new Date();
var myTxt = mots
var cntr=tiktak.getSeconds() % myTxt.length;
var phrases = myTxt[cntr]
document.getElementById(place).innerHTML = phrases
}
var stop = setInterval("showTxt('writeTxt')", 1000)
// -->
</script>
<p id="writeTxt"></p>
<form>
<input type="button" value="Заткнуть Остапа" onClick="clearInterval(stop);
document.getElementById('writeTxt').innerHTML = '<b>' +
mots[now.getSeconds()%mots.length].slice(0, 3) +
'...</b><img src=lsn_js24.files/offtopic.gif width=46 height=51>';
this.value='Вот так-то!'">
</form>

Итак:

 

Домашнее задание

Создайте метод — ну, скажем, getActualMonth().

Индексация месяцев с нуля часто запутывает. Когда мы выводим месяц на экран цифрой, нужно не забыть добавить в переменную +1. Поэтому сделайте метод, который уже это учитывает и выводит привычное «человеческое» число.

Шпоры не дам.


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

несколько приёмов работы с объектом Date.


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


 006336