Dart : parse date timezone gives UnimplementedError - date

I need to parse a date in the following format in my Flutter application (come from JSON) :
2019-05-17T15:03:22.472+0000
According to the documentation, I have to use Z to get the time zone (last 5 characters in RFC 822 format), so I use the following :
new DateFormat("y-M-d'T'H:m:s.SZ").parseStrict(json['startDate']);
But it fails with error :
FormatException: Characters remaining after date parsing in
2019-05-17T15:03:22.472+0000
Here is another test :
/// THIS WORKS
try {
print(new DateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS").format(DateTime.now()));
} catch (e) {
print(e.toString());
}
/// THIS RETURNS `UnimplementedError` (as soon as I use a 'Z' or 'z') somewhere
try {
print(new DateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(DateTime.now()));
} catch (e) {
print(e.toString());
}
Is Z implemented ?

Sadly z and v patterns are not implemented.
Those won't be implemented until Dart DateTime's have time zone information
More info on this issue https://github.com/dart-lang/intl/issues/19

From the DateFormat class docs:
DateFormat is for formatting and parsing dates in a locale-sensitive manner.
You're not asking to parse a locale-sensitive date string but rather an ISO 8601 date string, so thus you should not use the DateFormat class.
Instead, use the DateTime.parse method, which supports the format you described, per its docs:
Examples of accepted strings:
...
"2002-02-27T14:00:00-0500": Same as "2002-02-27T19:00:00Z"

You can use this format
print(new DateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(DateTime.now()));
It worked for me.

Related

Date time format : what is the format called?

Want to know what type of Date format is this : 2022-08-12T01:47:24.856316 , 2022-09-15T08:32:38.490Z
And how do i implement the current time to this format.
The format is known as ISO 8601, and you can parse and format it like this:
void main() {
print(DateTime.parse('2022-08-12T01:47:24.856316'));
print(DateTime.parse('2022-09-15T08:32:38.490Z'));
print(DateTime.now().toUtc().toIso8601String());
}
Output:
2022-08-12 01:47:24.856
2022-09-15 08:32:38.490Z
2023-01-28T07:28:29.865Z

Invalid Date Format Flutter

When parsing date and time from an API call which is formatted like this 2018 - 04 - 18T21:51:00 I get and error that states
and I don't understand what am I doing wrong.
/// I set in which format should my data be, and parse the data from the API call
Text('Date and Time:
${DateFormat("yyyy-MM-dd hh:mm:ss").format(DateTime.parse(apicall.timeanddate))}'),
After that I would format the Date and Time according to Locale language preference of the device.
Any help is appreciated.
The format you are passing is invalid, so you need to transform it:
String getDateTime(String dateFromServer){
dateFromServer = dateFromServer.replaceAll(" ","");
dateFromServer = dateFromServer.replaceAll("T"," ");
return dateFromServer;
}
I replaced all spaces and T that were causing problems you can now use this with:
DateFormat("yyyy-MM-dd hh:mm:ss").format(getDateTime(apicall.timeanddate));
Hope this would solve your problem.

Extract the date format from react-intl

I have a component that uses a datepicker. The datepicker needs a dateFormat property that fits the momentjs pattern, for example 'DD.MM.YYYY' or 'MM/DD/YYYY'.
The date formatting is handled by react-intl. This works fine when converting from a date to a string (via formatDate). However, I need to retrieve the pattern as described above.
My goal is to do something like
dateFormat = this.props.intl.extractDateFormat() // returns 'DD.MM.YYYY'
I have found this similar question, but the only answer relies on parsing the string, which I cannot do, because I do not know whether Day or Month will come first in the formatted date.
If it is possible to convert this string to a date and somehow retrieve the format from momentjs, that would also be a good solution.
I was able to get the date format from react-intl. To do this, I defined an example date and had it formatted by react-intl, and then parsed the format by referring to the original string.
My component which is exported as injectIntl(Component) has this method:
deriveDateFormat = () => {
const isoString = '2018-09-25' // example date!
const intlString = this.formatDate(isoString) // generate a formatted date
const dateParts = isoString.split('-') // prepare to replace with pattern parts
return intlString
.replace(dateParts[2], 'DD')
.replace(dateParts[1], 'MM')
.replace(dateParts[0], 'YYYY')
}
The date will e.g. be formatted to '09/25/2018', and this function would return 'MM/DD/YYYY', a format which can be used by Moment.js.
This function only works if you know that the month and day will always be displayed with two digits. It would fail if the format is something like 9/25/2018.
I have not found a way to extract the date format from react-intl directly.

SAPUI5 - Dateformat - How format a date with Dateformat

let's say I have a Date as a String, formated in yyyy-MM-dd, and I want it to be formated as style:"short".
I want just to use Dateformat.
I used this https://openui5.hana.ondemand.com/#docs/guide/91f2eba36f4d1014b6dd926db0e91070.html to get an idea of how to use DateFormat.
But I can't see, what's wrong with my code:
date: function(sdate) {
var regex = "[0-9]{4}-[0-9]{2}-[0-9]{2}";
if (!sdate.match(regex))
return "no valid date given";
jQuery.sap.require("sap.ui.core.format.DateFormat");
var oDateFormat = sap.ui.core.format.DateFormat.getInstance({pattern: "yyyy-MM-dd", style: "short"});
return oDateFormat.format(sdate); //date should be returned here in "short"-style
}
The console tell's me
TypeError: j.getTime is not a function.
Also it seems like the WebIDE doesn't know a function Datetime.format().
Can you help?
You'd probably reread the documentation in your link: to convert String into JS Date, you have to use DateFormat.parse method.

How to parse string with date, but without time in local format to ZonedDateTime?

This question is similar to How to parse ZonedDateTime with default zone? but addinitional condition.
I have a string param that represent a date in UK format: "3/6/09". It doesn't contain time, only date. But may contain it and even time zone.
And I want to parse it to ZonedDateTime.
public static ZonedDateTime parse(String value) {
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(SHORT).withLocale(Locale.UK).withZone(ZoneId.systemDefault());
TemporalAccessor temporalAccessor = formatter.parseBest(value, ZonedDateTime::from, LocalDateTime::from, LocalDate::from);
if (temporalAccessor instanceof ZonedDateTime) {
return ((ZonedDateTime) temporalAccessor);
}
if (temporalAccessor instanceof LocalDateTime) {
return ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault());
}
return ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault());
}
But, it fails with exception:
java.time.format.DateTimeParseException: Text '3/6/2009' could not be parsed at index 6
It's a bug for me, or isn't?
In my opinion is not a bug. Your approach is flawed.
First of all you are returning a ZonedDateTime so it is expected that the String contains full date, time and zone information. The string "3/6/09" should be parsed to a LocalDate.
Second, you are delegating a runtime detection of format to the library. Again, you should be parsing/formatting an expected format. Your application should know wether is expecting a full date & time or a partial (only date or only time).
Anyway you will have more luck detecting the format and then using different parsing methods.
Only local date:
DateTimeFormatter
.ofLocalizedDate(FormatStyle.SHORT)
.parse(value, LocalDate::from)`
Zoned date and time:
DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.SHORT)
.parse(value, ZonedDateTime::from)`
The format used can be seen using the getLocalizedDateTimePattern() method:
String fmt = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.UK);
The result is "dd/MM/yy HH:mm".
As such, the format is expecting both a date and a time with a space separator, so that is what must be provided.
In addition, the format/parse expects there to be two digits for the day-of-month and two digits for the month-of-year. Thus, you would need to pass in "03/06/09 00:00" in order to get the result you expect, in which case you can parse directly to a LocalDateTime.
Alternatively, use ofLocalizedDate():
DateTimeFormatter formatter =
DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(Locale.UK);
LocalDate date = LocalDate.parse("03/06/99", formatter);
Note that the input must still have two digits for the day and month.
Alternatively, parse using a specific pattern that can handle the missing leading zeroes:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yy");
LocalDate date = LocalDate.parse("3/6/99", formatter);
LocalDate date = LocalDate.parse("03/06/99", formatter);
// handles both "3/6/99" and "03/06/99"
Update: Lenient parsing also handles this case:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseLenient().appendPattern("dd/MM/yy").toFormatter();
LocalDate date = LocalDate.parse("3/6/99", formatter);
LocalDate date = LocalDate.parse("03/06/99", formatter);
// handles both "3/6/99" and "03/06/99"