March 26th, 2021

Учебник по JavaScript: ч.1, Типы данных, окончание

Дочитал пятый раздел («Типы данных») первой части («Язык программирования JavaScript») учебника по JavaScript.

https://learn.javascript.ru

Часть 1. Язык программирования JavaScript (в т.ч. 93 подраздела)

Разделы:

5. Типы данных (12 подразделов)

5.10 Деструктурирующее присваивание
5.11 Дата и время
5.12 Формат JSON, метод toJSON

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

let arr = ["Илья", "Чалов", "ЖЖ"];
let [firstName, surname] = arr;     // деструктурирующее присваивание

В этом примере во второй строке объявляются две новые переменные firstName и surname и им присваиваются значения из первого arr[0] и второго arr[1] элементов массива arr. Массив arr при этом не уничтожается, значения из него лишь считываются.

С помощью деструктурирующего присваивания авторы учебника ранее (в подразделе 5.5 «Методы массивов») интересно реализовали обмен значениями между двумя элементами одного массива в задаче «Перемешайте массив»:

[array[i], array[j]] = [array[j], array[i]];

Обычно, чтобы совершить обмен значениями между двумя переменными, используется дополнительная временная переменная:

let a = 3, b = 8, temp;

temp = a;
a = b;
b = temp;

Но с помощью деструктурирующего присваивания то же самое можно записать так:

let a = 3, b = 8;

[a, b] = [b, a];

По-моему, очень изящно.

Чехарда с «летним временем»

При чтении подраздела «Дата и время» в примерах постоянно получались нестыковки с часовым поясом.

Я нахожусь в городе Выборге (в Ленинградской области России), в котором используется московское время. Использую браузер «Microsoft Edge» и операционную систему «Windows 10 Pro». В примерах из указанного подраздела учебника местами попадается что-то вроде следующего:

alert( new Date() );           // Fri Mar 26 2021 02:32:04 GMT+0300 (Moscow Standard Time)
alert( new Date(2013, 0, 1) ); // Tue Jan 01 2013 00:00:00 GMT+0400 (Moscow Standard Time)

Здесь в комментариях я показал, что выдает мой браузер при выполнении этого кода. В первой строке на экран должны быть выданы текущие дата и время. А во второй строке — заданные дата и время (в данном примере — начало суток 1 января 2013 года). Московское время смещено на три часа относительно гринвичского (GMT), а, следовательно, должно обозначаться как GMT+0300. Однако, при выполнении второй строки этого примера, как видно, браузер выдает GMT+0400, то есть смещение на 4 часа.

Как оказалось, дело в переходе на так называемое «летнее время». В нашем часовом поясе «зимним временем» считается GMT+0300, а «летним временем» — GMT+0400, то есть перевод времени на час вперед.

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

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

https://www.iana.org/time-zones

В качестве примера чехарды с «летним временем» я поискал данные по своему часовому поясу (московское время) GMT+0300 и вот что узнал.

Регулярный перевод часов каждый год на «летнее время» (с конца марта до начала октября) в СССР был введен с 1981 года. Такая ситуация продолжалась до 2011 года. С 2 часов ночи 27 марта 2011 года по решению тогдашнего президента России Д. А. Медведева был совершен переход на постоянное «летнее время» GMT+0400 (без каких-либо обратных переходов). Это продолжалось до 27 октября 2014 года, когда по решению тогдашнего президента России В. В. Путина был совершен переход на постоянное «зимнее время» GMT+0300 (без каких-либо обратных переходов). После этого пока ситуация не менялась. В итоге в коде у меня получается следующее:

Годы после 1981 и до 2011 (регулярный ежегодный переход на «летнее время» и обратный возврат на «зимнее время»):
alert( new Date(2010, 0, 1) );  // GMT+03
alert( new Date(2010, 5, 1) );  // GMT+04 (летнее время)
alert( new Date(2010, 10, 1) ); // GMT+03

«Медведевский» период с 2 часов ночи 27.03.2011 года (постоянное «летнее время»):
alert( new Date(2011, 2, 27) ); // GMT+03
alert( new Date(2011, 2, 28) ); // GMT+04 (летнее время)

alert( new Date(2011, 5, 1) );  // GMT+04 (летнее время)
alert( new Date(2011, 10, 1) ); // GMT+04 (летнее время)

alert( new Date(2012, 0, 1) );  // GMT+04 (летнее время)

alert( new Date(2013, 0, 1) );  // GMT+04 (летнее время)

«Путинский» период с 27.10.2014 года (постоянное «зимнее время»):
alert( new Date(2014, 9, 26) ); // GMT+04 (летнее время)
alert( new Date(2014, 9, 27) ); // GMT+03

alert( new Date(2015, 0, 1) );  // GMT+03

alert( new Date(2021, 0, 1) );  // GMT+03

Подробнее про это можно почитать тут:

https://ru.wikipedia.org/wiki/Летнее_время

* * *

Ещё в этом подразделе учебника мне понравились некоторые приемы при решении задач. Например, вывод названия дня недели по заданному номеру дня недели. Я это всегда решал через конструкцию switch, но, как оказалось, можно проще и красивее:

let date = new Date();
let days = ["ВС", "ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ"];

alert( days[date.getDay()] );
(из задачи «Покажите день недели»)

А про то, как ловко отформатировать дату и время в строку с учетом того, что числа, обозначающие дату, месяц, число месяца, часы или минуты, могут быть с ведущим нулем, а могут и не быть с ведущим нулем, можно посмотреть в задаче «Форматирование относительной даты». Я для этого обычно использую громоздкие штабеля ветвлений if или условных операторов ()?:.

* * *

Много раз натыкался раньше (при изучении языка C++) на аббревиатуру «JSON», но всё руки не доходили. Подраздел 5.12 учебника раскрывает это понятие. Как оказалось, речь идет про сериализацию объекта в строку.

В принципе, ничего сложного, если понимать термин «сериализация» (я недавно писал о том, что это слово значит). Если кратко, то сериализация — это преобразование какой-то сложной структуры данных в последовательность бит или байтов (символов). Такое преобразование может потребоваться при сохранении объекта в память компьютера или при передаче объекта по сети (необходимость «последовательнизации» данных следует из физического устройства памяти и сети). В случае языка JavaScript речь идет о преобразовании в последовательность символов, то есть в строку. Например, какой-либо объект преобразуется в строку. Аббревиатура «JSON» расшифровывается как «JavaScript Object Notation», но, на самом деле, это отдельный стандарт, который по факту может использоваться (и используется) в разных языках программирования и средах разработки для обмена данными (поэтому эта аббревиатура и попадалась мне при изучении языка C++).