How to parse DateTime in Elixir? - date

How can I create (Ecto.)DateTime out of a tuple {DD, MM, YY}, or parse it from a string in Elixir? Should I use DateTime from Erlang for that?
I've googled but haven't found anything and there's nothing in the documentation about the matter, only about DateTime in general -- how to get the current date and time, for example.
Note that I don't want to use a third-party library such as Timex.

Just adding to the answer given by Justin. Elixir's standard library can parse ISO 8601 dates.
iex> Date.from_iso8601("2015-01-23")
{:ok, ~D[2015-01-23]}
or with the bang-version, that might raise errors:
iex> Date.from_iso8601!("2015-01-23")
~D[2015-01-23]
If you want a full datetime from an ISO 8601 string, you'll have to be satisfied with a NaiveDateTime, since there's no reliable time zone information to go on.
iex> NaiveDateTime.from_iso8601("2015-01-23 23:50:07")
{:ok, ~N[2015-01-23 23:50:07]}
Beware, it will simply throw away time zone offsets.
There is going to be a from_iso8601/1 on DateTime in the future, but it was recently added and has not been released as of Elixir v1.3.4. It will preserve time zone offset, but set the time zone to UTC.

To get the current date and or time, you can use one of
Ecto.Date.utc
Ecto.Time.utc
Ecto.DateTime.utc
DateTime.utc_now
As for converting a {DD, MM, YY} tuple into an Ecto.Date, you will not be able to do that with ecto provided functions. However, you can use a {YYYY, MM, DD} tuple to convert into Ecto.Date.
Ecto.Date.from_erl({2016, 12, 4})
#Ecto.Date<2016-12-04>
Date.from_erl({2016, 12, 4})
{:ok, ~D[2016-12-04]}
Ecto.Time.from_erl({13, 55, 10})
#Ecto.Time<12:10:08>
Ecto.Time.from_erl({13, 55, 10})
{:ok, ~T[13:55:10]}
Ecto.DateTime.from_erl({{2016, 12, 4}, {13, 55, 10}})
#Ecto.DateTime<2016-12-04 13:55:10>
Ecto.Date.from_erl({2016, 12, 4}) |> Ecto.DateTime.from_date()
#Ecto.Date<2016-12-04>
You just need to make sure your data is in the proper order these functions expect them to be.
As for parsing these from a string, you are either going to need to bring in another library, or write a parser yourself.

As Martin Svalin and Erik Vullings already commented here, you can now parse strings to DateTime in pure Elixir:
iex(5)> {:ok, date_time, offset} = DateTime.from_iso8601("2018-03-17 21:23:12+0100")
{:ok, #DateTime<2018-03-17 20:23:12Z>, 3600}
As you can see, I set an offset of +1 hour in my string. It was parsed correctly, but a DateTime object doesn't keep timezone information, and when I print it, it displays the correct date and time, but printed by default in UTC.
If you want to keep the original timezone information, that's stored as an offset in seconds in the third element of the tuple (offset in my example above).

Related

Type Date initial value

I try to set the initial value of Variable (Type: Date) to "2023-01-04 01:05:30.0".
I tried every combination, but I always get an error that the syntax is wrong.
The better (and non-deprecated) approach would be to use LocalDate and turn it into a Date:
LocalDateTime.of(2015, Month.JULY, 29, 19, 30, 40).atZone(ZoneId.systemDefault()).toInstant())
Read up on LocalDate and LocalDateTime as they are extremely useful for date manipulations. Only convert back to Date when all is computed and you need it for the model. See https://www.baeldung.com/java-date-to-localdate-and-localdatetime

Same unixtime yields different date time in joda than the correct date time

I read from a very old post here on stackoverflow that joda is a possible solution to convert Unix timestamp.
import org.joda.time._
new DateTime(1511544070).toString("yyyy-MM-dd")
I got 1970-01-18 for this case, however, this is wrong because the date should be
according to this online converter: 11/24/2017 # 5:21pm (UTC)
It is possible the online converter is correct because the sample unix timestamp 1511544070 is from a dataset that date range is November 25 to December 03, 2017, the dataset is from China time which is 8 hours ahead of UTC, meaning 11/24/2017 # 5:21pm (UTC) is actually 11/25/2017 # 1:21am (Beijing Time)
Where can I get a working library or is there a working library that can get the same result like the online converter?
You can do that using java.time:
import java.time.{ LocalDateTime, ZoneOffset }
import java.time.format.DateTimeFormatter
LocalDateTime.ofEpochSecond(1511544070, 0, ZoneOffset.UTC)
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd # h:mm a"))
Looking at the documentation for joda-time we see that a DateTime can take a Long specifying the milliseconds since 1 Jan 1970. However, you seem to be providing a value in seconds. Joda-time is actually calculating it correctly, since since 1511544070/(1000*3600*24) equals 17.49 days, i.e. 1970-01-18.
To get the expected result multiply with 1000:
new DateTime(1511544070*1000).toString("yyyy-MM-dd")
To get the time in another timezone, add withZone() as follows (for Shanghai/Beijing):
new DateTime(1511544070*1000).toString("yyyy-MM-dd")
.withZone(DateTimeZone.forID("Asia/Shanghai"))

Compare String time to Local Server Time

Have a string object with a specific format of date.
Need to check if that dateStr is after the current time on local machine.
Having trouble with conversions and LocalDateTime
String dateStr = "Oct 27 2017 02:29:00 GMT+0000";
public static final String DATE_FORMAT = "MMM dd yyyy HH:mm:ss zzzZ";
I know something is fishy in the below code with the usage of LocalDateTime
public static boolean isFutureDate(String dateStr){
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DATE_FORMAT);
LocalDateTime dateTime = LocalDateTime.parse(dateStr, formatter);
return(dateTime.isAfter(LocalDateTime.now()));
}
Trouble is with timezones and date conversions.
Please help find the right way of checking if a dateStr is after the current local date this in Java 8?
Local… types have no time zone
You are using the wrong type for your data.
The Local… types including LocalDateTime purposely have no concept of time zone or offset-from UTC. As such they not represent a moment on the time line, only rough idea of a range of possible moments. Use LocalDateTime only when the time zone is unknown or irrelevant; never use it for an actual moment in history.
Use OffsetDateDate for values with an offset-from-UTC, a number of hours and minutes.
Use ZonedDateTime for values with an assigned time zone. A time zone such as Asia/Kolkata or America/Montreal is a particular region’s history of past, present, and future changes to its offset-from-UTC. Anomalies such as Daylight Saving Time (DST) mean a change to the offset.
If you know all your inputs are in GMT/UTC, use OffsetDateTime. If the inputs may use time zones, parse as ZonedDateTime objects.
This input data format is terrible. If you have any control, use standard ISO 8601 formats instead when exchanging date-time values as text.
All this has been covered many times already on Stack Exchange. Please search more thoroughly before posting. And search Stack Overflow to learn more. I kept my Answer here brief, as this is a duplicate.
When parsing to a LocalDateTime, you're ignoring the offset (+0000), and I'm not sure if that's what you really want.
In this case, the +0000 offset means the date/time is October 27th 2017 at 02:29 AM in UTC. When you parse to a LocalDateTime, you're ignoring the offset (so it represents only "October 27th 2017 at 02:29 AM", not attached to any timezone) and comparing to your local date/time (or the current date/time in the JVM's default timezone).
If you want to make a comparison that also considers the offset, you can parse it to OffsetDateTime and convert to Instant to compare it with the actual UTC instant, regardless of the timezone.
Also, the month name is in English (I'm assuming it's English, but you can change this accordingly), so you must a java.util.Locale in the formatter (if you don't set a locale, it'll use the JVM default, and it's not guaranteed to always be English):
// parse to OffsetDateTime (use the same formatter)
String dateStr = "Oct 27 2017 02:29:00 GMT+0000";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM dd yyyy HH:mm:ss zzzZ", Locale.US);
OffsetDateTime odt = OffsetDateTime.parse(dateStr, fmt);
// compare Instant's
System.out.println(odt.toInstant().isAfter(Instant.now()));
Although it works for you now, keep in mind that the default locale can be changed without notice, even at runtime. If your input has locale-sensitive date (such as month names), it's better to specify it as above.

Powershell simplest method to get current time expressed as UTC

I have reviewed the post Creating a DateTime object with a specific UTC DateTime in PowerShell, but it does not seem to directly answer the question I am asking:
What is the most direct method in PowerShell (3.0) to return a sortable string representing "now" as UTC?
I expected the correct answer to be:
Get-Date -Format (Get-Culture).DateTimeFormat.UniversalSortableDateTimePattern
OR
get-date -format u
but this is not the case.
Example: At 1300 hrs (1pm) on September 1st, 2016 in the Pacific Time Zone during DST, I get the response:
2016-09-01 13:00:00Z (the local time with a "Z" appended)
when I was expecting:
2016-09-01 20:00:00Z (correct UTC/GMT time)
So basically, my code is just getting a string representing the "local" time and appending a "Z".
Now, I know I can manipulate to get to that point, but I'm looking for the minimal (simplest, cleanest) way to get here.
Bonus Points (as if they existed): How do I get that same, sortable result, but displaying with "UTC" and/or "GMT" as the suffix. Same minimal requirement.
Probably something like this:
[DateTime]::UtcNow.ToString('u')
Which is equivalent to:
[DateTime]::UtcNow.ToString((Get-Culture).DateTimeFormat.UniversalSortableDateTimePattern)
For the bonus, I think the most straightforward way is just to replace Z with UTC:
[DateTime]::UtcNow.ToString('u').Replace('Z','UTC')
I'm assuming you'll always want UTC since that what it seems like from your question. There doesn't appear to be a format string to get just the 3 letter time zone.
I tried this, and it also gives the result I want:
"[DateTime]::UtcNow.ToString('yyyyMMdd_HHmmss_UTC')"
It is showing time in the format 20180108_152407_UTC
so you can play with the date/time formatting as you wish basically

How to convert a ISO8601 date time string to a simple date time format in XSL version 1.0?

I have a ISO8601 string (e.g. date="2015-07-10T04:31:25") I need to convert this to the format:
July 7, 2015, 4:31:25 PM (EDT)
Even though I can write a template and use substring() to transform the string in the date time format. However I am not sure how to achieve the AM/PM and time zone information?
Working code templates would be highly appreciated. Thanks!
I am not sure how to achieve the AM/PM ...
It can be calculated from the hour component as:
substring('AMPM', 1 + 2*(number($hour) > 11), 2)
Of course, in the given input, where $hour would be "04", the correct result is "AM", not "PM".
... and time zone information?
Your input does not contain any time zone information, so unless you want to hard-code EDT as a string, there is no way to get it.