Import: be lenient with missing timezone information.

Fixes #249.
This commit is contained in:
Dennis Guse
2020-06-06 22:58:02 +02:00
parent 1f2e3bcf70
commit ed6ab9c53c
3 changed files with 21 additions and 4 deletions
+5
View File
@@ -50,6 +50,11 @@ def getVersionName = { ->
} }
android { android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
compileSdkVersion 29 compileSdkVersion 29
defaultConfig { defaultConfig {
@@ -128,6 +128,7 @@ public class StringUtilsTest {
*/ */
@Test @Test
public void testGetTime_timezone() { public void testGetTime_timezone() {
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); assertGetTime("2010-05-04T03:02:01Z", 2010, 5, 4, 3, 2, 1, 0);
assertGetTime("2010-05-04T03:02:01+00:00", 2010, 5, 4, 3, 2, 1, 0); assertGetTime("2010-05-04T03:02:01+00:00", 2010, 5, 4, 3, 2, 1, 0);
assertGetTime("2010-05-04T03:02:01-00:00", 2010, 5, 4, 3, 2, 1, 0); assertGetTime("2010-05-04T03:02:01-00:00", 2010, 5, 4, 3, 2, 1, 0);
@@ -20,12 +20,16 @@ import android.location.Location;
import android.os.Build; import android.os.Build;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.Log;
import android.util.Pair; import android.util.Pair;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.ParsePosition; import java.text.ParsePosition;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Instant; import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalAccessor;
import java.util.Date; import java.util.Date;
@@ -44,6 +48,8 @@ import de.dennisguse.opentracks.R;
*/ */
public class StringUtils { public class StringUtils {
private static final String TAG = StringUtils.class.getSimpleName();
private static final String COORDINATE_DEGREE = "\u00B0"; private static final String COORDINATE_DEGREE = "\u00B0";
//TODO Remove when upgrading to API level 26+. //TODO Remove when upgrading to API level 26+.
@@ -280,22 +286,27 @@ public class StringUtils {
} }
/** /**
* Gets the time, in milliseconds, from an XML date time string as defined at http://www.w3.org/TR/xmlschema-2/#dateTime * Gets the time, in milliseconds, from an XML date time string (ISO8601) as defined at http://www.w3.org/TR/xmlschema-2/#dateTime
* Let's be lenient: if timezone information is not provided, UTC will be used.
* *
* @param xmlDateTime the XML date time string * @param xmlDateTime the XML date time string
*/ */
public static long parseTime(String xmlDateTime) { public static long parseTime(String xmlDateTime) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try { try {
TemporalAccessor t = DateTimeFormatter.ISO_DATE_TIME.parse(xmlDateTime); TemporalAccessor t = DateTimeFormatter.ISO_DATE_TIME.parseBest(xmlDateTime, ZonedDateTime::from, LocalDateTime::from);
if (t instanceof LocalDateTime) {
Log.w(TAG, "Date does not contain timezone information: using UTC.");
t = ((LocalDateTime) t).atZone(ZoneOffset.UTC);
}
return Instant.from(t).toEpochMilli(); return Instant.from(t).toEpochMilli();
} catch (Exception e) { } catch (Exception e) {
throw new IllegalArgumentException("Invalid XML dateTime value: " + e); Log.e(TAG, "Invalid XML dateTime value");
throw e;
} }
} }
//TODO Remove the following when upgrading to API level 26+. //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 // Parse the date time base
ParsePosition position = new ParsePosition(0); ParsePosition position = new ParsePosition(0);