Skip to content

Commit

Permalink
Support timezone offsets in ISO8601 timestamps
Browse files Browse the repository at this point in the history
Issue: #3524

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=177808106
  • Loading branch information
ojw28 committed Dec 4, 2017
1 parent a9c3ca1 commit 9c63d37
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 26 deletions.
2 changes: 2 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
`DashMediaSource`, `SingleSampleMediaSource`.
* DASH:
* Support in-MPD EventStream.
* Support time zone designators in ISO8601 UTCTiming elements
([#3524](https://github.com/google/ExoPlayer/issues/3524)).
* Allow a back-buffer of media to be retained behind the current playback
position, for fast backward seeking. The back-buffer can be configured by
custom `LoadControl` implementations.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import android.os.Handler;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import com.google.android.exoplayer2.C;
Expand Down Expand Up @@ -51,6 +52,8 @@
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* A DASH {@link MediaSource}.
Expand Down Expand Up @@ -979,41 +982,42 @@ public Long parse(Uri uri, InputStream inputStream) throws IOException {

}

private static final class Iso8601Parser implements ParsingLoadable.Parser<Long> {
/* package */ static final class Iso8601Parser implements ParsingLoadable.Parser<Long> {

private static final String ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
private static final String ISO_8601_WITH_OFFSET_FORMAT = "yyyy-MM-dd'T'HH:mm:ssZ";
private static final String ISO_8601_WITH_OFFSET_FORMAT_REGEX_PATTERN = ".*[+\\-]\\d{2}:\\d{2}$";
private static final String ISO_8601_WITH_OFFSET_FORMAT_REGEX_PATTERN_2 = ".*[+\\-]\\d{4}$";
private static final Pattern TIMESTAMP_WITH_TIMEZONE_PATTERN =
Pattern.compile("(.+?)(Z|((\\+|-|−)(\\d\\d)(:?(\\d\\d))?))");

@Override
public Long parse(Uri uri, InputStream inputStream) throws IOException {
String firstLine = new BufferedReader(new InputStreamReader(inputStream)).readLine();

if (firstLine != null) {
//determine format pattern
String formatPattern;
if (firstLine.matches(ISO_8601_WITH_OFFSET_FORMAT_REGEX_PATTERN)) {
formatPattern = ISO_8601_WITH_OFFSET_FORMAT;
} else if (firstLine.matches(ISO_8601_WITH_OFFSET_FORMAT_REGEX_PATTERN_2)) {
formatPattern = ISO_8601_WITH_OFFSET_FORMAT;
} else {
formatPattern = ISO_8601_FORMAT;
try {
Matcher matcher = TIMESTAMP_WITH_TIMEZONE_PATTERN.matcher(firstLine);
if (!matcher.matches()) {
throw new ParserException("Couldn't parse timestamp: " + firstLine);
}
//parse
try {
SimpleDateFormat format = new SimpleDateFormat(formatPattern, Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
return format.parse(firstLine).getTime();
} catch (ParseException e) {
throw new ParserException(e);
// Parse the timestamp.
String timestampWithoutTimezone = matcher.group(1);
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));
long timestampMs = format.parse(timestampWithoutTimezone).getTime();
// Parse the timezone.
String timezone = matcher.group(2);
if ("Z".equals(timezone)) {
// UTC (no offset).
} else {
long sign = "+".equals(matcher.group(4)) ? 1 : -1;
long hours = Long.parseLong(matcher.group(5));
String minutesString = matcher.group(7);
long minutes = TextUtils.isEmpty(minutesString) ? 0 : Long.parseLong(minutesString);
long timestampOffsetMs = sign * (((hours * 60) + minutes) * 60 * 1000);
timestampMs -= timestampOffsetMs;
}

} else {
throw new ParserException("Unable to parse ISO 8601. Input value is null");
return timestampMs;
} catch (ParseException e) {
throw new ParserException(e);
}
}

}

}

0 comments on commit 9c63d37

Please sign in to comment.