Согласно МДН:
Дата в JavaScript определяется как время в миллисекундах, прошедшее с эпохи, которая определяется как полночь начала 1 января 1970 года по Гринвичу (эквивалентно эпохе UNIX). Эта отметка временинезависима от часового поясаи однозначно определяет момент в истории.
Мы знаем, что можем получить текущее время, используя Date.now()
. Что вернет нам количество миллисекунд прошедшее с полуночи в начале 1 января 1970 года по всемирному координированному времени.
Обычно дата и время хранятся в базе данных в отметке времени UNIX.
Временная метка UNIX – это числопрошедших с 1 января 1970 года.
Преобразование метки времени в прошедшее время (день, минуты и секунды)
Давайте возьмем пример, когда у нас есть сообщение в Facebook, и нам нужно показать в нем строку относительного времени. Если пост был сделан 17.05.2023, а сегодня 19.05.2023. В сообщении должно отображаться 2 days ago
. И вчера, если это было размещено 18 числа.
Сначала рассчитаем время между временем поста и текущим временем.
Мы получаем временную метку сообщения UNIX с сервера, и мы можем получить текущее время от Date.now()
.
Мы преобразуем метку времени UNIX (в секундах) в миллисекунды. Date.now()
возвращает нам время в миллисекундах.
мы можем рассчитать время, прошедшее в миллисекундах с момента публикации с помощью -
let currentTimestamp = Date.now(); let postTimestamp = getPostDateFromServer()*1000 let timePassedInMilliseconds = currentTimestamp - postTimestamp
Теперь у нас есть timePassedInMilliseconds
. Мы можем использовать его, чтобы вычислить, сколько дней, минут или секунд назад был сделан пост. Мы покажем X дней назад, если дней больше 0, иначе мы покажем ему X часов назад и так далее.
Мы также можем показывать пользователю годы и месяцы, но мы будем использовать только дни. Если дней больше 30. Мы показываем 31 день назад, а не 1 месяц назад.
Давайте сначала посчитаем, сколько миллисекунд в одном (день, час, минута и секунда)
let millsecInOneSec=1000; let millsecInOneMinute=60*millsecInOneSec; let millsecInOneHour=60*millsecInOneMinute; let millsecInOneDay=24*millsecInOneHour;
Теперь берем timePassedInMilliseconds
с момента публикации и считаем прошедшие дни, часы и минуты.
Мы можем вычислить unitOfTimePassed по таймфрейму/millsecInTimeframe, тогда мы можем Math.floor
UnitsOfTimePassed показать только единицу, а не ее дробную часть.
let unitsOfTimePassed; let timePassedString; let daysPassed = timePassedInMilliseconds/millsecInOneDay; let hoursPassed = timePassedInMilliseconds/millisecInOneHour; let minPassed = timePassedInMilliseconds/millisecInOneMin; let secPassed = timePassedInMilliseconds/millisecInOneSec; let unitTypes=['day','hour','minute','second'] let displayUnitType; if(daysPassed>1){ unitsOfTimePassed = Math.floor(daysPassed) displayUnitType=unitTypes[0] } else if(hoursPassed>1){ unitsOfTimePassed = Math.floor(hoursPassed) displayUnitType=unitTypes[1] } else if(minPassed>1){ unitsOfTimePassed = Math.floor(minPassed) displayUnitType=unitTypes[2] } else{ unitsOfTimePassed = Math.floor(secPassed) displayUnitType=unitTypes[3] }
Теперь, когда у нас есть unitsOfTimePassed
, мы можем создать нашу строку относительного времени. Для этого мы будем использовать Intl API. В частности, Intl.RelativeTimeFormat.
Что такое международный API??
Давайте узнаем, что такое Intl (интернационализация),
Согласно MDN это
Объект пространства имен
Intl
содержит несколько конструкторов, а также функции, общие для конструкторов интернационализации и других функций, зависящих от языка. В совокупности они составляют API-интерфейс интернационализации ECMAScript, который обеспечивает сравнение строк с учетом языка, форматирование чисел, форматирование даты и времени и многое другое.
Проще говоря, он предоставляет правильные строки для таких единиц, как (дата, время, число и количество), которые совместимы с разными языками и стилями письма в разных регионах.
Eg :
У нас может быть новостной веб-сайт, на котором мы показываем даты новостей в разных регионах на разных языках, для этого мы можем использовать Intl.DateTimeFormat
.
Обратите внимание, что в первом журнале мы использовали locale
как 'en-US'
, поэтому в нем используется дата в американском стиле. А во втором журнале у нас есть 'hi'
, что на хинди. Что делает дату в формате индийского хинди. В дате сначала идет день (19), а затем месяц, потому что это стиль, которому следует хинди, а в 'en-US'
месяц (май) идет первым.
Есть много других способов использования intl API, таких как Intl.Collator, Intl.ListFormat, Intl.NumberFormat, Intl.PluralRules
и т.д.
Использование Intl API для скрытия времени, перешедшего в относительное время
Мы будем использовать Intl.RelativeTimeFormat
, чтобы получить строку относительного времени для времени, прошедшего с момента публикации сообщения.
Мы уже знаем unitsOfTimePassed
и displayUnitType
, поэтому мы можем получить строку:
Мы настраиваем Intl.RelativeTimeFormat и locales
в соответствии с нашими потребностями.
const displayString = rtf.format(-1 * unitsOfTimePassed,displayUnitType );
Мы ставим -1, чтобы сообщить rtf
, что время прошло. Чтобы показать предстоящую дату, мы можем поставить +1.
Теперь мы можем использовать отображаемую строку в сообщении, чтобы показать пользователю относительное время с момента публикации сообщения.
ЕСЛИ ВАМ ПОНРАВИЛСЯ ПОСТ, ПОДЕЛИТЕСЬ ЕГО 😄.
Первоначально опубликовано на https://ghosty.hashnode.dev.