mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
datetime: add serialisation to and deserialisation from ISO 8601 strings
Some tag parsers and writers use same datetime format based on ISO 8601. We can reduce some code by creating some general functions for it. API: gst_date_time_to_iso8601_string() API: gst_date_time_new_from_iso8601_string() https://bugzilla.gnome.org/show_bug.cgi?id=678031
This commit is contained in:
parent
8b3708ea8c
commit
1eb9932dbb
4 changed files with 156 additions and 0 deletions
|
@ -2960,6 +2960,9 @@ gst_date_time_has_year
|
|||
gst_date_time_new_y
|
||||
gst_date_time_new_ym
|
||||
gst_date_time_new
|
||||
|
||||
gst_date_time_new_from_iso8601_string
|
||||
gst_date_time_to_iso8601_string
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "gstdatetime.h"
|
||||
#include <glib.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
* SECTION:gstdatetime
|
||||
|
@ -621,6 +622,152 @@ gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
|
|||
return datetime;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_date_time_to_iso8601_string:
|
||||
* @datetime: GstDateTime.
|
||||
*
|
||||
* Create a minimal string compatible with ISO-8601. Possible output formats
|
||||
* are (for example): 2012, 2012-06, 2012-06-23, 2012-06-23T23:30Z,
|
||||
* 2012-06-23T23:30+0100, 2012-06-23T23:30:59Z, 2012-06-23T23:30:59+0100
|
||||
*
|
||||
* Returns: a newly allocated string formatted according to ISO 8601 and
|
||||
* only including the datetime fields that are valid, or NULL in case
|
||||
* there was an error. The string should be freed with g_free().
|
||||
*/
|
||||
gchar *
|
||||
gst_date_time_to_iso8601_string (GstDateTime * datetime)
|
||||
{
|
||||
gfloat gmt_offset;
|
||||
|
||||
switch (datetime->fields) {
|
||||
case GST_DATE_TIME_FIELDS_Y:
|
||||
return g_date_time_format (datetime->datetime, "%Y");
|
||||
case GST_DATE_TIME_FIELDS_YM:
|
||||
return g_date_time_format (datetime->datetime, "%Y-%m");
|
||||
case GST_DATE_TIME_FIELDS_YMD:
|
||||
return g_date_time_format (datetime->datetime, "%F");
|
||||
case GST_DATE_TIME_FIELDS_YMD_HM:
|
||||
gmt_offset = gst_date_time_get_time_zone_offset (datetime);
|
||||
if (gmt_offset == 0)
|
||||
return g_date_time_format (datetime->datetime, "%FT%RZ");
|
||||
else
|
||||
return g_date_time_format (datetime->datetime, "%FT%R%z");
|
||||
case GST_DATE_TIME_FIELDS_YMD_HMS:
|
||||
gmt_offset = gst_date_time_get_time_zone_offset (datetime);
|
||||
if (gmt_offset == 0)
|
||||
return g_date_time_format (datetime->datetime, "%FT%TZ");
|
||||
else
|
||||
return g_date_time_format (datetime->datetime, "%FT%T%z");
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_date_time_new_from_iso8601_string:
|
||||
* @string: ISO 8601-formatted datetime string.
|
||||
*
|
||||
* Tries to parse common variants of ISO-8601 datetime strings into a
|
||||
* #GstDateTime.
|
||||
*
|
||||
* Free-function: gst_date_time_unref
|
||||
*
|
||||
* Returns: (transfer full): a newly created #GstDateTime, or NULL on error
|
||||
*/
|
||||
GstDateTime *
|
||||
gst_date_time_new_from_iso8601_string (const gchar * string)
|
||||
{
|
||||
gint year = -1, month = -1, day = -1, hour = -1, minute = -1, second = -1;
|
||||
gfloat tzoffset = 0.0;
|
||||
gint len, ret;
|
||||
|
||||
len = strlen (string);
|
||||
|
||||
g_return_val_if_fail (len >= 4, NULL);
|
||||
g_return_val_if_fail (g_ascii_isdigit (*string), NULL);
|
||||
|
||||
GST_DEBUG ("Parsing %s into a datetime", string);
|
||||
|
||||
ret = sscanf (string, "%04d-%02d-%02d", &year, &month, &day);
|
||||
|
||||
if (ret == 0)
|
||||
return NULL;
|
||||
else if (ret >= 1 && len < 16)
|
||||
/* YMD is 10 chars. XMD + HM will be 16 chars. if it is less,
|
||||
* it make no sense to continue. We will stay with YMD. */
|
||||
goto ymd;
|
||||
|
||||
string += 10;
|
||||
/* Exit if there is no expeceted value on this stage */
|
||||
if (!(*string == 'T' || *string == '-' || *string == ' '))
|
||||
goto ymd;
|
||||
|
||||
/* if hour or minute fails, then we will use onlly ymd. */
|
||||
hour = g_ascii_strtoull (string + 1, (gchar **) & string, 10);
|
||||
if (hour > 24 || *string != ':')
|
||||
goto ymd;
|
||||
|
||||
minute = g_ascii_strtoull (string + 1, (gchar **) & string, 10);
|
||||
if (minute > 59)
|
||||
goto ymd;
|
||||
|
||||
if (*string == ':') {
|
||||
second = g_ascii_strtoull (string + 1, (gchar **) & string, 10);
|
||||
/* if we fail here, we still can reuse hour and minute. We
|
||||
* will also fall of to tzoffset = 0.0 */
|
||||
if (second > 59)
|
||||
goto ymd_hms;
|
||||
}
|
||||
|
||||
if (*string == 'Z')
|
||||
goto ymd_hms;
|
||||
else {
|
||||
/* reuse some code from gst-plugins-base/gst-libs/gst/tag/gstxmptag.c */
|
||||
gint gmt_offset_hour = -1, gmt_offset_min = -1, gmt_offset = -1;
|
||||
gchar *plus_pos = NULL;
|
||||
gchar *neg_pos = NULL;
|
||||
gchar *pos = NULL;
|
||||
|
||||
GST_LOG ("Checking for timezone information");
|
||||
|
||||
/* check if there is timezone info */
|
||||
plus_pos = strrchr (string, '+');
|
||||
neg_pos = strrchr (string, '-');
|
||||
if (plus_pos)
|
||||
pos = plus_pos + 1;
|
||||
else if (neg_pos)
|
||||
pos = neg_pos + 1;
|
||||
|
||||
if (pos) {
|
||||
gint ret_tz;
|
||||
if (pos[2] == ':')
|
||||
ret_tz = sscanf (pos, "%d:%d", &gmt_offset_hour, &gmt_offset_min);
|
||||
else
|
||||
ret_tz = sscanf (pos, "%02d%02d", &gmt_offset_hour, &gmt_offset_min);
|
||||
|
||||
GST_DEBUG ("Parsing timezone: %s", pos);
|
||||
|
||||
if (ret_tz == 2) {
|
||||
gmt_offset = gmt_offset_hour * 60 + gmt_offset_min;
|
||||
if (neg_pos != NULL && neg_pos + 1 == pos)
|
||||
gmt_offset *= -1;
|
||||
|
||||
tzoffset = gmt_offset / 60.0;
|
||||
|
||||
GST_LOG ("Timezone offset: %f (%d minutes)", tzoffset, gmt_offset);
|
||||
} else
|
||||
GST_WARNING ("Failed to parse timezone information");
|
||||
}
|
||||
}
|
||||
|
||||
ymd_hms:
|
||||
return gst_date_time_new (tzoffset, year, month, day, hour, minute, second);
|
||||
ymd:
|
||||
return gst_date_time_new_ymd (year, month, day);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gst_date_time_free (GstDateTime * datetime)
|
||||
{
|
||||
|
|
|
@ -87,6 +87,10 @@ GstDateTime * gst_date_time_new_now_local_time (void) G_GNUC_MALLOC;
|
|||
|
||||
GstDateTime * gst_date_time_new_now_utc (void) G_GNUC_MALLOC;
|
||||
|
||||
|
||||
gchar * gst_date_time_to_iso8601_string (GstDateTime * datetime) G_GNUC_MALLOC;
|
||||
GstDateTime * gst_date_time_new_from_iso8601_string (const gchar * string) G_GNUC_MALLOC;
|
||||
|
||||
/* refcounting */
|
||||
|
||||
GstDateTime * gst_date_time_ref (GstDateTime * datetime);
|
||||
|
|
|
@ -279,6 +279,7 @@ EXPORTS
|
|||
gst_date_time_has_time
|
||||
gst_date_time_has_year
|
||||
gst_date_time_new
|
||||
gst_date_time_new_from_iso8601_string
|
||||
gst_date_time_new_from_unix_epoch_local_time
|
||||
gst_date_time_new_from_unix_epoch_utc
|
||||
gst_date_time_new_local_time
|
||||
|
@ -288,6 +289,7 @@ EXPORTS
|
|||
gst_date_time_new_ym
|
||||
gst_date_time_new_ymd
|
||||
gst_date_time_ref
|
||||
gst_date_time_to_iso8601_string
|
||||
gst_date_time_unref
|
||||
gst_debug_add_log_function
|
||||
gst_debug_bin_to_dot_file
|
||||
|
|
Loading…
Reference in a new issue