В одном из проектов, при создании календаря и панели аукционов, в очередной раз пришлось столкнуться с временем и часовыми поясами в JavaScript.
В JavaScript работа с датой и временем можно обойтись Date()
Вот если нужны специфические манипуляции, то тогда можно использовать библиотеки вроде moment.js
, luxon
, spacetime
, day.js
или date-fns
.
Сравнение в npmtrends — https://www.npmtrends.com/date-fns-vs-spacetime-vs-dayjs-vs-luxon-vs-moment
Выбор зависит от задачи и требований. Вкратце описание ситуации по часовым поясам есть в статье Habr «Работа с часовыми поясами в JavaScript» — https://habr.com/ru/company/mailru/blog/438286/
Обычно при стеке NodeJS (MongoDB) + JS framework дату сохраняем в базе как тип ISO date со смещением относительно времени сервера. Исходный код с примером из этой статьи можно взять из — bitbucket
let productSchema = new Schema({
title: String,
owner: String,
description: String,
comments: [{ body: String, date: Date }],
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: {
votes: Number,
favs: Number
},
qty: Number,
qrcode: String,
timeZone: String
});
// clientDateTime = "Fri Mar 8 2019 11:11:11 GMT+0300 (EET)";
let dateTime = `${clientDateTime}`;
// eventTimeZoneName = "Europe/Kiev";
let timeZone = `${eventTimeZoneName}`;
После сохранения в базе будет сохраненна дата : ISODate("2019-05-02T08:11:11.000Z")
Видим, что произошло смещение к дате по UTC.
Получение списка всех товаров (http://localhost:8081/products):
{
"products": [
{
"_id": "5ccbf1fbc518163a1ed37329",
"title": "Product5",
"owner": "Owner",
"comments": [],
"date": "2019-05-05T08:47:00.000Z",
"qty": 90
},
{
"_id": "5ccbf1fbc518163a1ed37328",
"title": "Product4",
"owner": "Owner",
"comments": [],
"date": "2019-05-04T08:47:00.000Z",
"qty": 78
},
{
"_id": "5ccbf1fbc518163a1ed37327",
"title": "Product3",
"owner": "Owner",
"comments": [],
"date": "2019-05-03T08:47:00.000Z",
"qty": 30
},
{
"_id": "5ccbf1fbc518163a1ed37326",
"title": "Product2",
"owner": "Owner",
"comments": [],
"date": "2019-05-02T08:47:00.000Z",
"qty": 42
},
{
"_id": "5ccbf1fbc518163a1ed37325",
"title": "Product1",
"owner": "Owner",
"comments": [],
"date": "2019-05-01T08:47:00.000Z",
"qty": 33
}
]
}
Отдельным запросом по API front-end получал товары сегоднешнего дня.
http://localhost:8081/products_today
{
"products": [
{
"_id": "5ccbf1fbc518163a1ed37327",
"title": "Product3",
"owner": "Owner",
"comments": [],
"date": "2019-05-03T08:47:00.000Z",
"qty": 30
}
]
}
А теперь выведем список дней этого месяца и количество товаров со средним количеством http://localhost:8081/products_calendar.
{
"products": [
{
"date": "2019-5-1",
"averageQuantity": 33,
"count": 1
},
{
"date": "2019-5-2",
"averageQuantity": 42,
"count": 1
},
{
"date": "2019-5-3",
"averageQuantity": 30,
"count": 1
},
{
"date": "2019-5-4",
"averageQuantity": 78,
"count": 1
},
{
"date": "2019-5-5",
"averageQuantity": 90,
"count": 1
}
]
}
Вывод списка товаров на front-end, для сегодняшнего дня выводит детальный список и точную дату.
Hello!
May 03, 2019 15:14 Europe/Vilnius
Date — 2019-5-1
Count — 1
AverageQuantity — 33
Date — 2019-5-2
Count — 1
AverageQuantity — 42
Date — 2019-5-3 (today)
Count — 1
AverageQuantity — 30
- Product3 ( 2019-05-03T08:47:00.000Z ) 11:47
Date — 2019-5-4
Count — 1
AverageQuantity — 78
Date — 2019-5-5
Count — 1
AverageQuantity — 90
Как видно из выше отображённого списка время — коректно.
Если выведем эту же страницу в часовом поясе — Asia/Shanghai
и America/New_York
Для запуска браузера в другом часовом поясе используем — TZ='Asia/Shanghai' google-chrome "--user-data-dir=$HOME/chrome-profile2"
Hello!
May 03, 2019 20:47 Asia/Shanghai
Date — 2019-5-1
Count — 1
AverageQuantity — 33
Date — 2019-5-2
Count — 1
AverageQuantity — 42
Date — 2019-5-3 (today)
Count — 1
AverageQuantity — 30
- Product3 ( 2019-05-03T08:47:00.000Z ) 16:47
Date — 2019-5-4
Count — 1
AverageQuantity — 78
Date — 2019-5-5
Count — 1
AverageQuantity — 90
Hello!
May 03, 2019 08:49 America/New_York
Date — 2019-5-1
Count — 1
AverageQuantity — 33
Date — 2019-5-2
Count — 1
AverageQuantity — 42
Date — 2019-5-3 (today)
Count — 1
AverageQuantity — 30
- Product3 ( 2019-05-03T08:47:00.000Z ) 04:47
Date — 2019-5-4
Count — 1
AverageQuantity — 78
Date — 2019-5-5
Count — 1
AverageQuantity — 90
Проверяем с
Vilnius, Lithuania Fri, 3 May 2019 at 11:47 EEST <br> Kyiv, Ukraine Fri, 3 May 2019 at 11:47 EEST <br> Beijing, China Fri, 3 May 2019 at 16:47 CST <br> New York, USA Fri, 3 May 2019 at 04:47 EDT
Для простого сохранения дат и их отображения в относительно времени клиента достаточно.
В следующей статье будет расмотрена ситуация когда нужно создать календарь с аукционами, которые запускаются только по времени начала и конца в определённые дни недели. То есть нету конкретной даты и времени с часовым поясом, а есть список дней и время начала и конца аукциона.
Добавить комментарий