Как получить дату в формате гггг-ММ-dd’T’HH: mm: ss.SSSZ

#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 , которому я должен передать an atom (), string () or binary () , и эта функция возвращает a DateTimeString , и мне нужно преобразовать его в string ()

4. Возвращаемое значение system_time_to_rfc3339 должно считаться как a string() , чтобы вы могли передать его 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