ThreeTenABP not parsing date - android

I am trying to convert ISO 8601 time into something human readable and in the local timezone of the Android device.
String date = "2016-09-24T06:24:01Z";
LocalDate test = LocalDate.parse(date, ISO_INSTANT);
But it returns:
method threw 'org.threeten.bp.format.DateTimeParseException' exception
From reading http://www.threeten.org/threetenbp/apidocs/org/threeten/bp/format/DateTimeFormatter.html#ISO_INSTANT it seems like what I'm doing should be possible.
What am I doing wrong?
Edit
Expanded exception error:
Unable to obtain LocalDate from TemporalAccessor: DateTimeBuilder[fields={MilliOfSecond=0, NanoOfSecond=0, InstantSeconds=1474698241, MicroOfSecond=0}, ISO, null, null, null], type org.threeten.bp.format.DateTimeBuilder
Edit 2
The solution is in the answer below. For anyone that stumbles across this, if you want to specify a custom output format you can use:
String format = "MMMM dd, yyyy \'at\' HH:mm a";
String dateString = DateTimeFormatter.ofPattern(format).withZone(ZoneId.systemDefault()).format(instant);

#alex answer is correct. Here is a working example.
Instant represents a point in time. To convert to any other local types you will need timezone.
String date = "2016-09-24T06:24:01Z";
This date string is parsed using the DateTimeFormatter#ISO_INSTANT internally.
Instant instant = Instant.parse(date);
From here you can convert to other local types just using timezone ( defaulting to system time zone )
LocalDateTime localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDate localDate = instant.atZone(ZoneId.systemDefault()).toLocalDate();
LocalTime localTime = instant.atZone(ZoneId.systemDefault()).toLocalTime();
Alternatively, you can use static method to get to local date time and then to local date and time.
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
LocalDate localDate = localDateTime.toLocalDate();
LocalTime localTime = localDateTime.toLocalTime();

You need to use Instant.parse().
This will give you an Instant that you can combine with a time zone to create a LocalDate.

In Kotlin:
Converts to LocalDateTime directly based on your local time zone::
val instant: Instant = Instant.parse("2020-04-21T02:22:04Z")
val localDateTime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime()
Converts to Date and time separately based on your local time zone:
val localDate: LocalDate = instant.atZone(ZoneId.systemDefault()).toLocalDate()
val localTime: LocalTime = instant.atZone(ZoneId.systemDefault()).toLocalTime()

Related

Get time from LocalDateTime

I'm looking to get the time from LocalDateTime (unless there is an easier way) with the format of HH:mm:a (12:34 pm)
Which Date/Time formatter do I want to use?
val sdf = SimpleDateFormat("HH:mm:a")
val dt = LocalDateTime.now().format(sdf)
print("Time: $dt")
I just managed to accomplish that the other way. Look at my code bellow.
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
fun main() {
val sdf = DateTimeFormatter.ofPattern("hh:mm:a")
val dt = LocalDateTime.now().format(sdf)
println("Time: $dt")
}
Reference:
Kotlin Program to Get Current Date/Time
tl;dr
(Using Java syntax.)
myLocalDateTime
.toLocalTime() // Extract the time only, without the date portion.
.format( // Automatically localize.
DateTimeFormatter
.ofLocalizedTime( FormatStyle.SHORT )
.withLocale( Locale.US )
)
Details
The Answer by Luiz is correct. I can show a couple of alternatives: extracting the time only, and automatically localizing.
If you want to focus on the time of day, extract a LocalTime object.
LocalTime lt = myLocalDateTime.toLocalTime() ;
Rather than hard-code a specific format, it is generally best to let java.time automatically localize.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedTime( FormatStyle.SHORT ).withLocale( Locale.US ) ;
String output = lt.format( f ) ;

How to Convert "2021-05-14T13:42:48.000Z" string to Date Object?

I am trying to convert "2021-05-14T13:42:48.000Z" string to Date Object.
I have tried this:
DateFormat dateFormat = new SimpleDateFormat("YYYY-MM-DDHH:MM:SS");
And also this, which i saw on stackoverflow only:-
DateFormat dateFormat = new SimpleDateFormat("YYYY-MM-DD'T'HH:MM:SS'A'");
But none of it worked.
How can i convert this string to my date object?
Assuming your date string always represents a UTC time (with the 'Z'), you can use format string:
yyyy-MM-dd'T'HH:mm:ss.SSSZ
but you'll first need to replace the Z in your date string with the fixed timezone "+0000", as in "2021-05-14T13:42:48.000+0000".
Try this:
String myDateString = "2021-05-14T13:42:48.000Z"
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US);
Date myDate = dateFormat.parse (myDateString.replace("Z","+0000"));
This will return a date correctly adjusted for your current timezone, in my case 9:42:48am EDT.
There is a more detailed discussion at Converting ISO 8601-compliant String to java.util.Date which you may find useful.
You have used the date-time format incorrectly. It's important to note that the date-time formats have different meanings between capitalized and small letters.
For example: Capital MM means months, whereas small mm means minutes.
To know more about the date formats, you can refer this:
https://cheatography.com/pezmat/cheat-sheets/date-time-formats/pdf/
or this:
https://devhints.io/datetime
And the answer for your case is:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
Please do not use SimpleDateFormat or even java.date. All these classes are deprecated.
Instead, rely on the Android available java.time package.
In short:
val source = "2021-05-14T13:42:48.000Z"
val parsed = ZonedDateTime.parse(source)
This will correctly parse the timezone (Z for Zulu/UTC/GMT).
You can verify this, by simply converting the parsed Zoned date time into, for example, Europe/Amsterdam time (which is +2).
val source = "2021-05-14T13:42:48.000Z"
val parsed = ZonedDateTime.parse(source)
parsed.toString() // prints: 2021-05-14T13:42:48Z
parsed.zone // prints: "Z"
ZoneId.of(parsed.zone.id) // returns the ZoneOffset "Z" (correct)
// Convert to Amsterdam Time
val amsterdamDateTime = parsed.withZoneSameInstant(ZoneId.of("Europe/Amsterdam"))
amsterdamDateTime.toString() // prints: 2021-05-14T15:42:48+02:00[Europe/Amsterdam] (2 hours ahead of the Zulu time, also correct).
parsed.format(DateTimeFormatter.ISO_DATE_TIME).toString() // Prints: 2021-05-14T13:42:48Z (correct)
So as you can see, these classes do the right thing (most of the time).
I suggest you use them.

Kotlin convert DateTime to 10 digit TimeStamp

I'm trying to find out how I can convert DateTime to 10 digit timestamp in Kotlin (Android Studio), I can't find any equivalent of it in Kotlin.
For example:
I have a val with date-time value like :
val dateTime = "2020-12-13 17:54:00"
Now I want to convert it to 10 digit timestamp like "1607842496"
Please give me a simple sample to show how I can resolve this problem. Thanks in advance.
Use the SimpleDateFormat class to parse your date String to a Date object. You can then get the timestamp (in milliseconds) from that Date object like so:
val dateTime = "2020-12-13 17:54:00"
val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
val date = simpleDateFormat.parse(dateTime)
val timestamp = date?.time
Divide the timestamp by a 1000 to get the 10 digit (in seconds) timestamp.

OffsetDateTime to Date Android

I am getting an OffsetDateTime from our backend in a String format like this:
"2017-07-15T10:52:59Z"
I am trying to parse this String to a Android Date:
private SimpleDateFormat mSimpleDateFormat;
private static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
mSimpleDateFormat = new SimpleDateFormat(DATE_FORMAT_PATTERN, Locale.getDefault());
Date newDate = null;
String dateString = notice.getCreated();
try {
newDate = mSimpleDateFormat.parse(dateString);
} catch (ParseException e) {
LogHelper.showExceptionLog(MyClass.class, e);
}
It always throws:
Unparseable date: "2017-07-15T10:52:59Z"
To parse the Z (which is the UTC designator) you must use the X pattern (as explained in javadoc):
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
String dateString = "2017-07-15T10:52:59Z";
Date newDate = mSimpleDateFormat.parse(dateString);
If you use just yyyy-MM-dd'T'HH:mm:ss as a pattern, SimpleDateFormat will use the system's default timezone and ignore the Z, giving incorrect results: it'll parse the date/time as 10:52 in the default timezone, which can be different to 10:52 in UTC. By using the X pattern, you get the correct result.
I also removed the Locale because this formatter is not dealing with any locale-sensitive information (like month and day of week names), so it doesn't affect the parsing in this case (and SimpleDateFormat already uses the default locale if you don't specify one).
PS: the X pattern was introduced in JDK 7. If you're using and older version, it won't be available. In this case, you can set the UTC as a timezone of the formatter:
SimpleDateFormat mSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
mSimpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Obviously this code is assuming that the input is always in UTC (with Z in the end).
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
For Android, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need ThreeTenABP (more on how to use it here).
As the input string is in ISO 8601 format, you can easily parse it to a org.threeten.bp.OffsetDateTime:
String dateString = "2017-07-15T10:52:59Z";
OffsetDateTime odt = OffsetDateTime.parse(dateString);
You can then convert this to a java.util.Date easily, using the org.threeten.bp.DateTimeUtils class:
Date date = DateTimeUtils.toDate(odt.toInstant());
If the input is always in UTC (always with the Z in the end), you can also use a org.threeten.bp.Instant:
String dateString = "2017-07-15T10:52:59Z";
Instant instant = Instant.parse(dateString);
Date date = DateTimeUtils.toDate(instant);
The only difference is that Instant only parses UTC inputs (ending with Z) and OffsetDateTime accepts any valid UTC offset (like -03:00 or +05:30).

Joda-Time return Wrong Date

Well Im using Joda-time
I want to convert the Georgian to Hijri date but it return the wrong date from georgian to hijri.
Im doing like this
TimeZone timeZone = TimeZone.getTimeZone("UTC+05:00"); // Pakistan Time Zone
DateTimeZone datetimeZone = DateTimeZone.forTimeZone(timeZone);
Chronology iso = ISOChronology.getInstance(datetimeZone);
Chronology hijri = IslamicChronology.getInstance(datetimeZone);
LocalDate todayGeorgian = new LocalDate(2014,04,13), iso); //Today's Date
LocalDate todayHijri = new LocalDate(todayGeorgian.toDateTimeAtStartOfDay()), hijri);
todayHijri.toString(); // This must return **1435-06-13** but returns 1435-06-12
Problem appears when you do redundant call of LocalDate#toDateTimeAtStartOfDay() method.
LocalDate object is timezone independent, but when you convert it to DateTime (by #toDateTimeAtStartOfDay() method ), it becomes zone dependent.
After it you convert DateTime to LocalDate again.
This conversions cause the issue.
Please, don't use LocalDate#toDateTimeAtStartOfDay() here:
Chronology iso = ISOChronology.getInstance(datetimeZone);
Chronology hijri = IslamicChronology.getInstance(datetimeZone);
LocalDate todayGeorgian = new LocalDate(2014, 04, 13, iso); //Today's Date
LocalDate todayHijri = new LocalDate(todayGeorgian, hijri);
EDIT
Also "UTC+05:00" is not valid zone for TimeZone. Use:
DateTimeZone datetimeZone = DateTimeZone.forID("Etc/GMT+5");

Categories

Resources