Joda: how to generate an ISO datetime string with "Z" at the and - scala

I generate an ISO datetime string (without time zone) like this:
val dateTime: LocalDateTime = LocalDateTime.now
val dateTimeStr: String = ISODateTimeFormat.dateTime.withZone(DateTimeZone.UTC).print(dateTime)
The code above produces the following string:
2014-04-10T06:13:19.283
Now I need to convert this string back to a LocalDateTime...
val dateTime = LocalDateTime.parse(dateTimeStr, ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC))
... and compare it with the current time:
val isBefore = dateTime.isBefore(LocalDateTime.now)
The code above doesn't work and produces the following error:
Invalid format: \"2014-04-27T17:51:06.780\" is too short
To fix the problem, I need to append a Z to dateTimeStr:
val dateTime = LocalDateTime.parse(s"${dateTimeStr}Z", ISODateTimeFormat.dateTime().withZone(DateTimeZone.UTC))
Is there a way to generate the ISO datetime string with the Z at the end?

A LocalDateTime has NO timezone. So you cannot associate a timezone-aware format (Z stands for UTC timezone) with this zoneless data type.
If you insist on having Z-formats then you have to work with a global type like DateTime. So you have two different steps. One step is object conversion between local and global type:
LocalDateTime ldt = ...;
DateTime dt = ldt.toDateTime(DateTimeZone.UTC); // or another timezone
// reverse
DateTime dt = ...;
LocalDateTime ldt = dt.toLocalDateTime();
Second step is conversion between formatted string form and global timestamp:
LocalDateTime ldt = ...;
DateTime dt = ldt.toDateTime(DateTimeZone.UTC); // or another timezone
String iso = ISODateTimeFormat.dateTime().print(dt);
// reverse
String iso = ...; // with trailing Z or another timezone information
DateTime dt = IsoDateTimeFormat.parseDateTime(iso);
LocalDateTime ldt = dt.toLocalDateTime();
Finally you can combine these two steps for conversion between ISO-format with timezone information and a LocalDateTime as shown in the second step.
If you only need formatted strings without any timezone or offset information then you can stick the global type DateTime completely and just use localDateOptionalTimeParser() as #Sebastian has correctly mentioned.

Try to use
val dateTime: DateTime = DateTime.now
instead of
val dateTime: LocalDateTime = LocalDateTime.now
Or if you want to stick to LocalDateTime change the parsing:
val dateTime = LocalDateTime.parse(dateTimeStr) // this uses the default localDateOptionalTimeParser

Related

How to convert correctly only time in dart

i've a string like this
String time = '13:00:00Z'; (Zulu time)
I want to convert it into a string in the correct local time.
For example if i execute the program, i want 15:00 as a result because 13:00 in my local time it's 15:00.
I get the error "FormatExeption: Invalid date format", whatever I put in the DateFormat
You can prepend current date to the time string and then use toLocal() to convert it to your local time:
DateTime date = DateTime.now();
String formattedDate = DateFormat('yyyy-MM-dd').format(date);
String time = "13:00:00Z";
DateTime dt = DateTime.parse(formattedDate + "T" + time).toLocal();
String formattedTime = DateFormat('HH:mm').format(dt);
print(formattedTime);
(DateFormat is from the intl package)

How to convert unix timestamp to iso 8601 in Flutter

I am getting date from a server as a unix timestamp, how can I convert it to ISO 8601 date format in flutter?
the date I receive:
1611694800000
How I want to convert it to be
2021-01-26T22:00:00.000+00:00
What I have done so far with no luck
String s = '1611694800000';
debugPrint("Recevied date is: $s");
String dateS = DateTime.parse(s).toIso8601String();
debugPrint("Converted date : $dateS");
String dateStr = (dateS.split(".")[0].split("T")[0] + " 00:00:00").substring(1);
debugPrint("Activation date: $dateStr");
I end up getting:
Unhandled Exception: FormatException: Invalid date format.
Use DateTime.fromMillisecondsSinceEpoch:
var timestampMilliseconds = 1611694800000;
var datetime =
DateTime.fromMillisecondsSinceEpoch(timestampMilliseconds, isUtc: true);
print(datetime.toIso8601String()); // Prints: 2021-01-26T21:00:00.000Z
(Note that the printed time is one hour off of your stated expectation, but I'm assuming that's a mistake in your expectation.)
The reason why you are getting invalid date format is because you have to provide date in string like '2021-04-19' and not milliseconds;
This package makes it easy to format dates time_formatter

Elm : How to get YESTERDAY date in String Date

Let's say I have this Model:
type alias Model =
{ currentDate : String
, yesterdayDate : String
}
The CurrentDate I got from Html input type date (Date Picker) is in format YYYY-MM-DD
Html Form
input [ name "date", type_ "date", onInput UpdateDate ] []
Update.elm
UpdateDate date ->
let
-- Get Yesterday Date function here
in
( { model | currentDate = date, yesterdayDate = "" }, Cmd.none )
In this situation , how can i get yesterday Date in String ?
My idea is parse the day into INT and using subtraction method to get Yesterday day but I cannot find any way to do it... Any help is appreciate.
Convert the string date to Posix, convert the Posix to milliseconds since epoch, subtract the amount of milliseconds in a day, convert the resulting milliseconds back to Posix and the Posix to an ISO8601 string. Take the first 10 characters from that string.
module Main exposing (main)
import Browser
import Html exposing (Html, button, div, text)
import Html.Events exposing (onClick)
import Iso8601
import Time exposing (Posix)
sampleDate =
"2020-05-01"
subtractDays : Int -> Posix -> Posix
subtractDays days time =
(Time.posixToMillis time - (days * 24 * 60 * 60 * 1000))
|> Time.millisToPosix
subtractDaysFromIsoDate : Int -> String -> String
subtractDaysFromIsoDate days date =
Iso8601.toTime date
|> Result.map (subtractDays days >> Iso8601.fromTime >> String.left 10)
|> Result.withDefault date
main =
text <| subtractDaysFromIsoDate 1 sampleDate
Note that in this implementation if the string is not a valid date it will just be returned unmodified rather than fail. You might want to capture that this operation can fail.
As you can trust that you get a valid string format from html and are aware of the date package, you can split the date string into 3 strings, convert each into an integer and then construct today and yesterday as a Date value.
Questions you should ask yourself:
Do you really want to store the date as a String? The Date type might be more useful if you want to do something else then just display the string value.
And do you really want to store both today and yesterday? The latter can be easily computed when needed.
Example for string splitting:
case
String.split "-" date
|> List.map String.toInt
of
[ Just year, Just monthInt, Just day ] ->
-- convert monthInt to `Month`
-- construct current date
-- add -1 `Day`
Debug.todo "todo" 2
_ ->
Debug.todo "invalid date format" date

Java 8 LocalDateTime has different results

I am trying to update some code to use Java 8's feature for parsing multiple date formats. my local time on my box is set to UTC-11.
the below code works when using the SimpleDateformat.
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date correctDate = dateFormat.parse("2018-09-6T03:28:59.039-04:00");
//Gives me correct date
System.println( correctDate);//Wed Sep 5th 20:28:59 GMT-11:00 2018
I am trying to update this code to give the same date as above with the DateTimeFormatter in Java 8 , so i can handle another date format..
DateTimeFormattter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX");
LocalDateTime updateDate = LocalDateTime.parse( "2018-09-6T03:28:59.039-04:00", dtf);
//shows the wrong date of 2018-09-06 03:28:59.039.
System.out.println( updateDate.toString() );// 2018-09-06 03:28:59.039
[solved]
I was able to fix this by using ZonedDateTime.
ZonedDateTime zdt = ZonedDateTime.parse("2018-09-6T03:28:59.039-04:00");
zonedDateTime = zdt.withZoneSameInstance(ZoneId.of("GMT"));
Date correctDate = Date.from( zonedDateTime.toInstance());
//correctDate is what i wanted Wed Sep 5th 20:28:59 GMT-11:00 2018
As soon as you parse your date string into a LocalDateTime the zone offset is lost because LocalDateTime does not hold any time zone or offset information.
When you format the LocalDateTime to a string again, you'll only have the time as it was parsed without offset.
The Documentation of LocalDateTime clearly explains this:
This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.
You should consider using OffsetDateTime or ZonedDateTime.
Solved, using OffsetDateTime as suggested in the accepted 'Answer':
OffsetDateTime odt = OffsetDateTime.parse("2018-09-6T03:28:59.039-04:00");
Date correctDate = Date.from( odt.toInstant());

Day from date Scala

I'd like to get the day from a date object as an integer. This is my code so far.
val dateString = "2015-11-24 23:23:09"
val format = new java.text.SimpleDateFormat("yyyy-MM-dd H:m:s")
val date = format.parse(dateString)
print(date) # this gives Tue Nov 24 23:23:09 CST 2015
Now, from date, I want to get the day of the month as an integer. How do I do that?
Thanks.
Just use the Java Calendar class (although I would recommend moving over to the Joda library if you are doing much serious work with dates/times):
val cal = Calendar.getInstance()
cal.setTime(date)
val dayOfMonth = cal.get(Calendar.DAY_OF_MONTH)
tl;dr
LocalDateTime.parse(
"2015-11-24 23:23:09".replace( " " , "T" )
).getDayOfMonth()
java.time
The modern approach uses the java.time classes.
Using Java syntax here as I don't know Scala. Note that java.time uses immutable objects.
Convert your string to comply with ISO 8601 standard format with a T in the middle.
String input = "2015-11-24 23:23:09".replace( " " , "T" ) ;
Parse as an LocalDateTime as your input lacks any time zone or offset-from-UTC.
LocalDateTime ldt = LocalDateTime.parse( input ) ;
Interrogate for the day of month.
int dom = ldt.getDayOfMonth() ;
Using Joda,
org.joda.time.DateTime.now().getDayOfMonth()
or equivalently,
import java.util.Date
new org.joda.time.DateTime(new Date()).getDayOfMonth