#date #erlang
#Дата #erlang
Вопрос:
Я хочу получить текущее время и отформатировать его следующим образом:
гггг-ММ-дд’т’Ч: мм: ss.SSSZ
(где SSS — миллисекунды, а Z — часовой пояс)
код до сих пор у меня выглядит следующим образом:
formatted_date() ->
{{Y,M,D},{H,Min,S}} = erlang:localtime(),
{Ms, _, _} = os:timestamp(),
{Days, {Hours, _,_}} = calendar:time_difference(erlang:universaltime(), erlang:localtime()),
Difference = 24*Days Hours,
Tz = [case Difference < 0 of
true ->
$-;
false ->
$
end | io_lib:format("~2..0B00",[Difference])],
io_lib:format("[~4..0B-~2..0B-~2..0BT~2..0B:~2..0B:~2..0B.~3..0B ~5.s]",
[Y, M, D, H, Min, S, Ms, Tz]).
Дело в том, что он всегда возвращает одну и ту же Мс, поэтому я думаю, что у меня это плохо получается, и в других вопросах я вижу только, как получить общее время в миллисекундах, но не как его отформатировать таким образом.
Спасибо.
Ответ №1:
Самый простой способ — использовать библиотечную функцию calendar:system_time_to_rfc3339/2
— кажется, она удовлетворяет всем вашим требованиям.
> calendar:system_time_to_rfc3339(os:system_time(millisecond), [{unit, millisecond}]).
"2021-03-03T18:42:08.497 05:30"
Эта функция была добавлена в Erlang / OTP 21.0, который был выпущен в июне 2018 года.
Причина, по которой ваш код всегда получает одно и то же значение Ms
, заключается в том, что первое значение в возвращаемом кортеже os:timestamp/0
— это мегасекунды, а не миллисекунды; три значения — мегасекунды, секунды и микросекунды. Это относится к тому времени, когда Erlang не поддерживал большие целые числа, поэтому было необходимо разделить временную метку. В наши дни вы можете просто вызвать os:system_time/1
или ряд других функций, в зависимости от того, какое время вам нужно, и получить результат в виде одного целого числа.
Комментарии:
1. Важным аспектом этого превосходного ответа является то, что он извлекает время только один раз и преобразует его в нужный формат. В исходном коде в вопросе
localtime
вызывается дважды иuniversaltime
один раз, что означает, что вычисления в коде выполняются с использованием нескольких разных значений времени, и возможно, что смещение часового пояса может измениться между извлечениями этих разных времен, что приведет к неверному результату.2. У меня это не работает. Теперь я пытаюсь получить os:timestamp() {Mega, Seconds, Micro} и отформатировать его
yyyy-MM-dd'T'HH:mm:ss.SSSZ
, но я не могу найти способ вернуть миллиметр…3. Хорошо, я думаю, я знаю, почему это не работает для меня, поскольку у меня есть a
io_lib:format/2
, которому я должен передать anatom (), string () or binary ()
, и эта функция возвращает aDateTimeString
, и мне нужно преобразовать его вstring ()
4. Возвращаемое значение
system_time_to_rfc3339
должно считаться как astring()
, чтобы вы могли передать егоio_lib:format
следующим образом:io_lib:format("Current timestamp: ~s~n", [calendar:system_time_to_rfc3339(os:system_time(millisecond), [{unit, millisecond}])])
5. Это не работает, потому что версия erlang, с которой я работаю, равна 17, а эта функция имеет более высокую версию. Итак… Я ищу функцию, которая позволяет мне это делать и была в версии 17