From 32070a0bd6ae1929e4cfc475337dbb491f3db64c Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Wed, 8 Jan 2020 21:15:27 +0100 Subject: [PATCH] Use java.time instead of custom code for parsing (requires API 26+). This is a functional change on API26+ as a timezone identifier is required. --- .../AbstractTestFileTrackImporter.java | 6 ++-- .../opentracks/util/StringUtilsTest.java | 23 ++++--------- .../importer/AbstractFileTrackImporter.java | 2 +- .../opentracks/util/StringUtils.java | 34 ++++++++++++++++--- 4 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java index fad7a03f1..47ab81745 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/AbstractTestFileTrackImporter.java @@ -57,9 +57,9 @@ public abstract class AbstractTestFileTrackImporter { static final double TRACK_ELEVATION = 324.0; static final String TRACK_TIME_0 = "2010-04-22T18:21:00Z"; - static final String TRACK_TIME_1 = "2010-04-22T18:21:50.123"; - static final String TRACK_TIME_2 = "2010-04-22T18:23:00.123"; - static final String TRACK_TIME_3 = "2010-04-22T18:24:50.123"; + static final String TRACK_TIME_1 = "2010-04-22T18:21:50.123Z"; + static final String TRACK_TIME_2 = "2010-04-22T18:23:00.123Z"; + static final String TRACK_TIME_3 = "2010-04-22T18:24:50.123Z"; static final SimpleDateFormat DATE_FORMAT_0 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'", Locale.US); static final SimpleDateFormat DATE_FORMAT_1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS", Locale.US); diff --git a/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java b/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java index 2c2fc2819..2836f8131 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/util/StringUtilsTest.java @@ -115,27 +115,16 @@ public class StringUtilsTest { } /** - * Tests {@link StringUtils#getTime(String)}. - */ - @Test - public void testGetTime() { - assertGetTime("2010-05-04T03:02:01", 2010, 5, 4, 3, 2, 1, 0); - assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0); - } - - /** - * Tests {@link StringUtils#getTime(String)} with fractional seconds. + * Tests {@link StringUtils#parseTime(String)} with fractional seconds. */ @Test public void testGetTime_fractional() { - assertGetTime("2010-05-04T03:02:01.3", 2010, 5, 4, 3, 2, 1, 300); - assertGetTime("2010-05-04T03:02:01.35", 2010, 5, 4, 3, 2, 1, 350); assertGetTime("2010-05-04T03:02:01.352Z", 2010, 5, 4, 3, 2, 1, 352); - assertGetTime("2010-05-04T03:02:01.3529Z", 2010, 5, 4, 3, 2, 1, 353); + assertGetTime("2010-05-04T03:02:01.3529Z", 2010, 5, 4, 3, 2, 1, 352); } /** - * Tests {@link StringUtils#getTime(String)} with time zone. + * Tests {@link StringUtils#parseTime(String)} with time zone. */ @Test public void testGetTime_timezone() { @@ -149,7 +138,7 @@ public class StringUtilsTest { } /** - * Tests {@link StringUtils#getTime(String)} with fractional seconds and time zone. + * Tests {@link StringUtils#parseTime(String)} with fractional seconds and time zone. */ @Test public void testGetTime_fractionalAndTimezone() { @@ -160,7 +149,7 @@ public class StringUtilsTest { } /** - * Asserts the {@link StringUtils#getTime(String)} returns the expected values. + * Asserts the {@link StringUtils#parseTime(String)} returns the expected values. * * @param xmlDateTime the xml date time string * @param year the expected year @@ -175,7 +164,7 @@ public class StringUtilsTest { GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC")); calendar.set(year, month - 1, day, hour, minute, second); calendar.set(GregorianCalendar.MILLISECOND, millisecond); - Assert.assertEquals(calendar.getTimeInMillis(), StringUtils.getTime(xmlDateTime)); + Assert.assertEquals(calendar.getTimeInMillis(), StringUtils.parseTime(xmlDateTime)); } /** diff --git a/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java b/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java index df884ad77..fdbd27d11 100644 --- a/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java +++ b/src/main/java/de/dennisguse/opentracks/io/file/importer/AbstractFileTrackImporter.java @@ -412,7 +412,7 @@ abstract class AbstractFileTrackImporter extends DefaultHandler implements Track timeValue = trackData.importTime; } else { try { - timeValue = StringUtils.getTime(time); + timeValue = StringUtils.parseTime(time); } catch (IllegalArgumentException e) { throw new SAXException(createErrorMessage(String.format(Locale.US, "Unable to parse time: %s", time)), e); } diff --git a/src/main/java/de/dennisguse/opentracks/util/StringUtils.java b/src/main/java/de/dennisguse/opentracks/util/StringUtils.java index 69f0d0155..8091a8c9c 100644 --- a/src/main/java/de/dennisguse/opentracks/util/StringUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/StringUtils.java @@ -17,6 +17,7 @@ package de.dennisguse.opentracks.util; import android.content.Context; import android.location.Location; +import android.os.Build; import android.text.TextUtils; import android.text.format.DateUtils; import android.util.Pair; @@ -24,6 +25,9 @@ import android.util.Pair; import java.text.DecimalFormat; import java.text.ParsePosition; import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAccessor; import java.util.Date; import java.util.Locale; import java.util.TimeZone; @@ -42,8 +46,16 @@ public class StringUtils { private static final String COORDINATE_DEGREE = "\u00B0"; + //TODO Remove when upgrading to API level 26+. + @Deprecated private static final SimpleDateFormat ISO_8601_DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); + + //TODO Remove when upgrading to API level 26+. + @Deprecated private static final SimpleDateFormat ISO_8601_BASE = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US); + + //TODO Remove when upgrading to API level 26+. + @Deprecated private static final Pattern ISO_8601_EXTRAS = Pattern.compile("^(\\.\\d+)?(?:Z|([+-])(\\d{2}):(\\d{2}))?$"); static { @@ -51,7 +63,6 @@ public class StringUtils { ISO_8601_BASE.setTimeZone(TimeZone.getTimeZone("UTC")); } - private StringUtils() { } @@ -73,7 +84,11 @@ public class StringUtils { * @param time_ms the time in milliseconds */ public static String formatDateTimeIso8601(long time_ms) { - return ISO_8601_DATE_TIME_FORMAT.format(time_ms); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + return Instant.ofEpochMilli(time_ms).toString(); + } else { + return ISO_8601_DATE_TIME_FORMAT.format(time_ms); + } } /** @@ -269,8 +284,19 @@ public class StringUtils { * * @param xmlDateTime the XML date time string */ - //TODO Can this be replaced using java.time? - public static long getTime(String xmlDateTime) { + public static long parseTime(String xmlDateTime) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + try { + TemporalAccessor t = DateTimeFormatter.ISO_DATE_TIME.parse(xmlDateTime); + return Instant.from(t).toEpochMilli(); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid XML dateTime value: " + e); + } + } + + //TODO Remove the following when upgrading to API level 26+. + //ATTENTION: The following code does not require a time zone (+01 or Z); while ISO_DATE_TIME requires this! + // Parse the date time base ParsePosition position = new ParsePosition(0); Date date = ISO_8601_BASE.parse(xmlDateTime, position);