--- 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 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel