datetimetimezoneelixirectodatetime-conversion

How to Convert updated_at to Conventional 12 Hour Format with My Time Zone?


In Phoenix, Ecto gives me a timestamp named updated_at, and it presents time in this way:

2023-05-31T18:44:44

I want to format it to 12 hour time and convert it to my time zone.

I can format it to a 12-hour time style while not affecting the time zone by doing this:

Calendar.strftime(updated_at,"%d-%m-%y %I:%M:%S %p")

This gives me a format that looks like this:

31-05-23 06:59:01 PM

This is what I want, but the time zone is still incorrect.

I don't need to store the time with my time zone to the database, I just need to render the preexisting time data to the GUI formatted the way I described.

I could parse the string, turn the relevant parts into integers, do the math and re-stringify it, but I figure there might be a simpler answer.

My time zone is 5 hours less than the time recorded to the database.


Solution

  • First, instead of a string, it would be better to store the datetime in your database as a datetime, and configure ecto to return it as a DateTime by using timestamps(type: :utc_datetime_usec) (or :utc_datetime) in your schema.

    However, assuming you just have the string 2023-05-31T18:44:44, you can do this:

    1. Convert your string to a NaiveDateTime using NaiveDateTime.from_iso8601!/2
    2. Convert the NaiveDateTime to a DateTime, specifying the time zone the data is stored in using DateTime.from_naive/3
    3. Convert the DateTime to your time zone using DateTime.shift_zone/3
    4. Format the DateTime as you are already doing with Calendar.strftime/3

    You need to have installed and configured a time zone database.

    Example, assuming Europe/London and America/New_York time zones (note the result can vary, but it works out to 5 hours for this date):

    "2023-05-31T18:44:44"
    |> NaiveDateTime.from_iso8601!()
    |> DateTime.from_naive!("Europe/London")
    |> DateTime.shift_zone!("America/New_York")
    |> Calendar.strftime("%d-%m-%y %I:%M:%S %p")
    

    Result:

    "31-05-23 01:44:44 PM"
    

    If you have configured Ecto to give you DateTimes in UTC, you can skip the first two steps (but New York is actually 4 hours behind UTC at that date, so the result will differ).