[FFmpeg-devel] [PATCH 1/2] lavu/utils: add av_parse_iso8601_tz; use it in time parsing functions
Rodger Combs
rodger.combs at gmail.com
Wed Nov 11 06:20:42 CET 2015
---
libavformat/utils.c | 20 ++++++++++++--------
libavutil/parseutils.c | 43 +++++++++++++++++++++++++++++++++++++++++--
libavutil/parseutils.h | 18 +++++++++++++++---
3 files changed, 68 insertions(+), 13 deletions(-)
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 5c4d452..f70f91e 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -4168,14 +4168,18 @@ int ff_find_stream_index(AVFormatContext *s, int id)
int64_t ff_iso8601_to_unix_time(const char *datestr)
{
- struct tm time1 = { 0 }, time2 = { 0 };
- const char *ret1, *ret2;
- ret1 = av_small_strptime(datestr, "%Y - %m - %d %T", &time1);
- ret2 = av_small_strptime(datestr, "%Y - %m - %dT%T", &time2);
- if (ret2 && !ret1)
- return av_timegm(&time2);
- else
- return av_timegm(&time1);
+ struct tm time = { 0 };
+ const char *ret = av_small_strptime(datestr, "%Y - %m - %d %T", &time);
+ if (!ret)
+ ret = av_small_strptime(datestr, "%Y - %m - %dT%T", &time);
+ if (ret) {
+ const char *ret2 = av_parse_iso8601_tz(ret, &time);
+ if (ret2)
+ ret = ret2;
+ return av_timegm(&time);
+ } else {
+ return -1;
+ }
}
int avformat_query_codec(const AVOutputFormat *ofmt, enum AVCodecID codec_id,
diff --git a/libavutil/parseutils.c b/libavutil/parseutils.c
index 9fb8d0a..ff47d35 100644
--- a/libavutil/parseutils.c
+++ b/libavutil/parseutils.c
@@ -536,6 +536,40 @@ char *av_small_strptime(const char *p, const char *fmt, struct tm *dt)
return (char*)p;
}
+char *av_parse_iso8601_tz(const char *p, struct tm *dt)
+{
+ if (!p || !*p)
+ return NULL;
+ if (*p == 'Z' || *p == 'z') {
+ p++;
+ } else if (*p == '-' || *p == '+') {
+ int neg = (*p == '+') ? -1 : 1;
+ const char *min;
+ p++;
+ if (p[0] < '0' || p[0] > '9' ||
+ p[1] < '0' || p[1] > '9')
+ return NULL;
+ dt->tm_hour += neg * (
+ (p[0] - '0') * 10 +
+ (p[1] - '0'));
+ p += 2;
+ min = p;
+ if (*min == ':')
+ min++;
+ if (min[0] >= '0' && min[0] <= '9' &&
+ min[1] >= '0' && min[1] <= '9') {
+ dt->tm_min += neg * (
+ (min[0] - '0') * 10 +
+ (min[1] - '0'));
+ p = min + 2;
+ }
+ } else {
+ return NULL;
+ }
+
+ return (char*)p;
+}
+
time_t av_timegm(struct tm *tm)
{
time_t t;
@@ -652,8 +686,13 @@ int av_parse_time(int64_t *timeval, const char *timestr, int duration)
if (duration) {
t = dt.tm_hour * 3600 + dt.tm_min * 60 + dt.tm_sec;
} else {
- int is_utc = *q == 'Z' || *q == 'z';
- q += is_utc;
+ int is_utc = 0;
+ const char *ptz = av_parse_iso8601_tz(q, &dt);
+ if (ptz) {
+ is_utc = 1;
+ q = ptz;
+ }
+
if (today) { /* fill in today's date */
struct tm dt2 = is_utc ? *gmtime_r(&now, &tmbuf) : *localtime_r(&now, &tmbuf);
dt2.tm_hour = dt.tm_hour;
diff --git a/libavutil/parseutils.h b/libavutil/parseutils.h
index e66d24b..673d750 100644
--- a/libavutil/parseutils.h
+++ b/libavutil/parseutils.h
@@ -125,12 +125,12 @@ const char *av_get_known_color_name(int color_idx, const uint8_t **rgb);
* @param timestr a string representing a date or a duration.
* - If a date the syntax is:
* @code
- * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH:MM:SS[.m...]]]}|{HHMMSS[.m...]]]}}[Z]
+ * [{YYYY-MM-DD|YYYYMMDD}[T|t| ]]{{HH:MM:SS[.m...]]]}|{HHMMSS[.m...]]]}}[Z|z|{-|+}HH[[:]MM]]
* now
* @endcode
* If the value is "now" it takes the current time.
- * Time is local time unless Z is appended, in which case it is
- * interpreted as UTC.
+ * Time is local time unless a time zone specifier is appended, in which case
+ * it is interpreted in that time zone ("Z" means UTC).
* If the year-month-day part is not specified it takes the current
* year-month-day.
* - If a duration the syntax is:
@@ -186,6 +186,18 @@ int av_find_info_tag(char *arg, int arg_size, const char *tag1, const char *info
char *av_small_strptime(const char *p, const char *fmt, struct tm *dt);
/**
+ * Parser for ISO 8601 time zone specifiers
+ *
+ * Works similarly to a %z in glibc's strptime. Applies the specified offset
+ * to the existing time in dt. This may result in the tm_hour and tm_min
+ * members being out of their normal ranges.
+ *
+ * @return a pointer to the first character not processed in this function
+ * call. See av_small_strptime().
+ */
+char *av_parse_iso8601_tz(const char *p, struct tm *dt);
+
+/**
* Convert the decomposed UTC time in tm to a time_t value.
*/
time_t av_timegm(struct tm *tm);
--
2.6.2
More information about the ffmpeg-devel
mailing list