datetime: allow GstDateTime where not all fields are set
[platform/upstream/gstreamer.git] / gst / gstdatetime.c
1 /* GStreamer
2  * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "glib-compat-private.h"
25 #include "gst_private.h"
26 #include "gstdatetime.h"
27 #include <glib.h>
28 #include <math.h>
29
30 /**
31  * SECTION:gstdatetime
32  * @title: GstDateTime
33  * @short_description: A date, time and timezone structure
34  *
35  * Struct to store date, time and timezone information altogether.
36  * #GstDateTime is refcounted and immutable.
37  *
38  * Date information is handled using the proleptic Gregorian calendar.
39  *
40  * Provides basic creation functions and accessor functions to its fields.
41  *
42  * Since: 0.10.31
43  */
44
45 #define GST_DATE_TIME_SEC_PER_DAY          (G_GINT64_CONSTANT (86400))
46 #define GST_DATE_TIME_USEC_PER_DAY         (G_GINT64_CONSTANT (86400000000))
47 #define GST_DATE_TIME_USEC_PER_HOUR        (G_GINT64_CONSTANT (3600000000))
48 #define GST_DATE_TIME_USEC_PER_MINUTE      (G_GINT64_CONSTANT (60000000))
49 #define GST_DATE_TIME_USEC_PER_SECOND      (G_GINT64_CONSTANT (1000000))
50 #define GST_DATE_TIME_USEC_PER_MILLISECOND (G_GINT64_CONSTANT (1000))
51
52 typedef enum
53 {
54   BAD_DATE,
55   HAS_Y,                        /* has year */
56   HAS_YM,                       /* has year and month */
57   HAS_YMD,                      /* has year mont and day */
58   HAS_YMD_H,
59   HAS_YMD_HM,
60   HAS_YMD_HMS
61 } DateTimeFields;
62
63 struct _GstDateTime
64 {
65   GDateTime *datetime;
66
67   DateTimeFields fields;
68   volatile gint ref_count;
69 };
70
71 static GstDateTime *
72 gst_date_time_new_from_gdatetime (GDateTime * dt)
73 {
74   GstDateTime *gst_dt;
75
76   if (!dt)
77     return NULL;
78
79   gst_dt = g_slice_new (GstDateTime);
80   gst_dt->datetime = dt;
81   gst_dt->ref_count = 1;
82   return gst_dt;
83 }
84
85 /**
86  * gst_date_time_has_year:
87  * @datetime: a #GstDateTime
88  *
89  * Returns the TRUE if year exist
90  *
91  * Since:
92  */
93 gboolean
94 gst_date_time_has_year (const GstDateTime * datetime)
95 {
96   return (datetime->fields >= HAS_Y) ? 1 : 0;
97 }
98
99 /**
100  * gst_date_time_has_month:
101  * @datetime: a #GstDateTime
102  *
103  * Returns the TRUE if month exist
104  *
105  * Since:
106  */
107 gboolean
108 gst_date_time_has_month (const GstDateTime * datetime)
109 {
110   return (datetime->fields >= HAS_YM) ? 1 : 0;
111 }
112
113 /**
114  * gst_date_time_has_day:
115  * @datetime: a #GstDateTime
116  *
117  * Returns the TRUE if day exist
118  *
119  * Since:
120  */
121 gboolean
122 gst_date_time_has_day (const GstDateTime * datetime)
123 {
124   return (datetime->fields >= HAS_YMD) ? 1 : 0;
125 }
126
127 /**
128  * gst_date_time_has_hour:
129  * @datetime: a #GstDateTime
130  *
131  * Returns the TRUE if hour exist
132  *
133  * Since:
134  */
135 gboolean
136 gst_date_time_has_hour (const GstDateTime * datetime)
137 {
138   return (datetime->fields >= HAS_YMD_H) ? 1 : 0;
139 }
140
141 /**
142  * gst_date_time_has_minute:
143  * @datetime: a #GstDateTime
144  *
145  * Returns the TRUE if minute exist
146  *
147  * Since:
148  */
149 gboolean
150 gst_date_time_has_minute (const GstDateTime * datetime)
151 {
152   return (datetime->fields >= HAS_YMD_HM) ? 1 : 0;
153 }
154
155 /**
156  * gst_date_time_has_second:
157  * @datetime: a #GstDateTime
158  *
159  * Returns the TRUE if second exist
160  *
161  * Since:
162  */
163 gboolean
164 gst_date_time_has_second (const GstDateTime * datetime)
165 {
166   return (datetime->fields >= HAS_YMD_HMS) ? 1 : 0;
167 }
168
169 /**
170  * gst_date_time_get_year:
171  * @datetime: a #GstDateTime
172  *
173  * Returns the year of this #GstDateTime
174  * Call gst_date_time_has_year before, to avoid warnings.
175  *
176  * Return value: The year of this #GstDateTime
177  * Since: 0.10.31
178  */
179 gint
180 gst_date_time_get_year (const GstDateTime * datetime)
181 {
182   g_return_val_if_fail (gst_date_time_has_year (datetime), 0);
183   return g_date_time_get_year (datetime->datetime);
184 }
185
186 /**
187  * gst_date_time_get_month:
188  * @datetime: a #GstDateTime
189  *
190  * Returns the month of this #GstDateTime. January is 1, February is 2, etc..
191  * Call gst_date_time_has_month before, to avoid warnings.
192  *
193  * Return value: The month of this #GstDateTime
194  * Since: 0.10.31
195  */
196 gint
197 gst_date_time_get_month (const GstDateTime * datetime)
198 {
199   g_return_val_if_fail (gst_date_time_has_month (datetime), 0);
200   return g_date_time_get_month (datetime->datetime);
201 }
202
203 /**
204  * gst_date_time_get_day:
205  * @datetime: a #GstDateTime
206  *
207  * Returns the day of this #GstDateTime.
208  * Call gst_date_time_has_day before, to avoid warnings.
209  *
210  * Return value: The day of this #GstDateTime
211  * Since: 0.10.31
212  */
213 gint
214 gst_date_time_get_day (const GstDateTime * datetime)
215 {
216   g_return_val_if_fail (gst_date_time_has_day (datetime), 0);
217   return g_date_time_get_day_of_month (datetime->datetime);
218 }
219
220 /**
221  * gst_date_time_get_hour:
222  * @datetime: a #GstDateTime
223  *
224  * Retrieves the hour of the day represented by @datetime in the gregorian
225  * calendar. The return is in the range of 0 to 23.
226  * Call gst_date_time_has_haur before, to avoid warnings.
227  *
228  * Return value: the hour of the day
229  *
230  * Since: 0.10.31
231  */
232 gint
233 gst_date_time_get_hour (const GstDateTime * datetime)
234 {
235   g_return_val_if_fail (gst_date_time_has_hour (datetime), 0);
236   return g_date_time_get_hour (datetime->datetime);
237 }
238
239 /**
240  * gst_date_time_get_minute:
241  * @datetime: a #GstDateTime
242  *
243  * Retrieves the minute of the hour represented by @datetime in the gregorian
244  * calendar.
245  * Call gst_date_time_has_minute before, to avoid warnings.
246  *
247  * Return value: the minute of the hour
248  *
249  * Since: 0.10.31
250  */
251 gint
252 gst_date_time_get_minute (const GstDateTime * datetime)
253 {
254   g_return_val_if_fail (gst_date_time_has_minute (datetime), 0);
255   return g_date_time_get_minute (datetime->datetime);
256 }
257
258 /**
259  * gst_date_time_get_second:
260  * @datetime: a #GstDateTime
261  *
262  * Retrieves the second of the minute represented by @datetime in the gregorian
263  * calendar.
264  * Call gst_date_time_has_second before, to avoid warnings.
265  *
266  * Return value: the second represented by @datetime
267  *
268  * Since: 0.10.31
269  */
270 gint
271 gst_date_time_get_second (const GstDateTime * datetime)
272 {
273   g_return_val_if_fail (gst_date_time_has_second (datetime), 0);
274   return g_date_time_get_second (datetime->datetime);
275 }
276
277 /**
278  * gst_date_time_get_microsecond:
279  * @datetime: a #GstDateTime
280  *
281  * Retrieves the fractional part of the seconds in microseconds represented by
282  * @datetime in the gregorian calendar.
283  *
284  * Return value: the microsecond of the second
285  *
286  * Since: 0.10.31
287  */
288 gint
289 gst_date_time_get_microsecond (const GstDateTime * datetime)
290 {
291   return g_date_time_get_microsecond (datetime->datetime);
292 }
293
294 /**
295  * gst_date_time_get_time_zone_offset:
296  * @datetime: a #GstDateTime
297  *
298  * Retrieves the offset from UTC in hours that the timezone specified
299  * by @datetime represents. Timezones ahead (to the east) of UTC have positive
300  * values, timezones before (to the west) of UTC have negative values.
301  * If @datetime represents UTC time, then the offset is zero.
302  *
303  * Return value: the offset from UTC in hours
304  * Since: 0.10.31
305  */
306 gfloat
307 gst_date_time_get_time_zone_offset (const GstDateTime * datetime)
308 {
309   return (g_date_time_get_utc_offset (datetime->datetime) /
310       G_USEC_PER_SEC) / 3600.0;
311 }
312
313 /**
314  * gst_date_time_new_y:
315  * @year: the gregorian year
316  *
317  * Creates a new #GstDateTime using the date and times in the gregorian calendar
318  * in the local timezone.
319  *
320  * @year should be from 1 to 9999.
321  *
322  * Free-function: gst_date_time_unref
323  *
324  * Return value: (transfer full): the newly created #GstDateTime
325  *
326  * Since:
327  */
328 GstDateTime *
329 gst_date_time_new_y (gint year)
330 {
331   GstDateTime *datetime;
332   datetime = gst_date_time_new_local_time (year, 1, 1, 1, 1, 1);
333   datetime->fields = HAS_Y;
334   return datetime;
335 }
336
337 /**
338  * gst_date_time_new_ym:
339  * @year: the gregorian year
340  * @month: the gregorian month
341  *
342  * Creates a new #GstDateTime using the date and times in the gregorian calendar
343  * in the local timezone.
344  *
345  * @year should be from 1 to 9999, @month should be from 1 to 12.
346  *
347  * If value is -1 then all over value will be ignored. For example
348  * if @month == -1, then #GstDateTime will created only for @year.
349  *
350  * Free-function: gst_date_time_unref
351  *
352  * Return value: (transfer full): the newly created #GstDateTime
353  *
354  * Since:
355  */
356 GstDateTime *
357 gst_date_time_new_ym (gint year, gint month)
358 {
359   GstDateTime *datetime;
360   datetime = gst_date_time_new_local_time (year, month, 1, 1, 1, 1);
361   datetime->fields = HAS_YM;
362   return datetime;
363 }
364
365 /**
366  * gst_date_time_new_ymd:
367  * @year: the gregorian year
368  * @month: the gregorian month
369  * @day: the day of the gregorian month
370  *
371  * Creates a new #GstDateTime using the date and times in the gregorian calendar
372  * in the local timezone.
373  *
374  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
375  * 1 to 31.
376  *
377  * If value is -1 then all over value will be ignored. For example
378  * if @month == -1, then #GstDateTime will created only for @year. If
379  * @day == -1, then #GstDateTime will created for @year and @month and
380  * so on.
381  *
382  * Free-function: gst_date_time_unref
383  *
384  * Return value: (transfer full): the newly created #GstDateTime
385  *
386  * Since:
387  */
388 GstDateTime *
389 gst_date_time_new_ymd (gint year, gint month, gint day)
390 {
391   GstDateTime *datetime;
392   datetime = gst_date_time_new_local_time (year, month, day, 1, 1, 1);
393   datetime->fields = HAS_YMD;
394   return datetime;
395 }
396
397 /**
398  * gst_date_time_new_ymd_h:
399  * @year: the gregorian year
400  * @month: the gregorian month
401  * @day: the day of the gregorian month
402  * @hour: the hour of the day
403  *
404  * Creates a new #GstDateTime using the date and times in the gregorian calendar
405  * in the local timezone.
406  *
407  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
408  * 1 to 31, @hour from 0 to 23.
409  *
410  * If value is -1 then all over value will be ignored. For example
411  * if @month == -1, then #GstDateTime will created only for @year. If
412  * @day == -1, then #GstDateTime will created for @year and @month and
413  * so on.
414  *
415  * Free-function: gst_date_time_unref
416  *
417  * Return value: (transfer full): the newly created #GstDateTime
418  *
419  * Since:
420  */
421 GstDateTime *
422 gst_date_time_new_ymd_h (gint year, gint month, gint day, gint hour)
423 {
424   GstDateTime *datetime;
425   datetime = gst_date_time_new_local_time (year, month, day, hour, 1, 1);
426   datetime->fields = HAS_YMD_H;
427   return datetime;
428 }
429
430 /**
431  * gst_date_time_new_ymd_hm:
432  * @year: the gregorian year
433  * @month: the gregorian month
434  * @day: the day of the gregorian month
435  * @hour: the hour of the day
436  * @minute: the minute of the hour
437  *
438  * Creates a new #GstDateTime using the date and times in the gregorian calendar
439  * in the local timezone.
440  *
441  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
442  * 1 to 31, @hour from 0 to 23, @minutes from 0 to 59.
443  *
444  * If value is -1 then all over value will be ignored. For example
445  * if @month == -1, then #GstDateTime will created only for @year. If
446  * @day == -1, then #GstDateTime will created for @year and @month and
447  * so on.
448  *
449  * Free-function: gst_date_time_unref
450  *
451  * Return value: (transfer full): the newly created #GstDateTime
452  *
453  * Since:
454  */
455 GstDateTime *
456 gst_date_time_new_ymd_hm (gint year, gint month, gint day, gint hour,
457     gint minute)
458 {
459   GstDateTime *datetime;
460   datetime = gst_date_time_new_local_time (year, month, day, hour, minute, 1);
461   datetime->fields = HAS_YMD_HM;
462   return datetime;
463 }
464
465 /**
466  * gst_date_time_new_from_unix_epoch_local_time:
467  * @secs: seconds from the Unix epoch
468  *
469  * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
470  * @secs. The #GstDateTime is in the local timezone.
471  *
472  * Free-function: gst_date_time_unref
473  *
474  * Return value: (transfer full): the newly created #GstDateTime
475  *
476  * Since: 0.10.31
477  */
478 GstDateTime *
479 gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
480 {
481   GstDateTime *datetime;
482   datetime =
483       gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_local (secs));
484   datetime->fields = HAS_YMD_HMS;
485   return datetime;
486 }
487
488 /**
489  * gst_date_time_new_from_unix_epoch_utc:
490  * @secs: seconds from the Unix epoch
491  *
492  * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
493  * @secs. The #GstDateTime is in the UTC timezone.
494  *
495  * Free-function: gst_date_time_unref
496  *
497  * Return value: (transfer full): the newly created #GstDateTime
498  *
499  * Since: 0.10.31
500  */
501 GstDateTime *
502 gst_date_time_new_from_unix_epoch_utc (gint64 secs)
503 {
504   GstDateTime *datetime;
505   datetime =
506       gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_utc (secs));
507   datetime->fields = HAS_YMD_HMS;
508   return datetime;
509 }
510
511 static DateTimeFields
512 gst_date_time_check_fields (gint * year, gint * month, gint * day,
513     gint * hour, gint * minute, gdouble * seconds)
514 {
515   if (*month == -1) {
516     *month = *day = *hour = *minute = *seconds = 1;
517     return HAS_Y;
518   } else if (*day == -1) {
519     *day = *hour = *minute = *seconds = 1;
520     return HAS_YM;
521   } else if (*hour == -1) {
522     *hour = *minute = *seconds = 1;
523     return HAS_YMD;
524   } else if (*minute == -1) {
525     *minute = *seconds = 1;
526     return HAS_YMD_H;
527   } else if (*seconds == -1) {
528     *seconds = 1;
529     return HAS_YMD_HM;
530   } else
531     return HAS_YMD_HMS;
532 }
533
534 /**
535  * gst_date_time_new_local_time:
536  * @year: the gregorian year
537  * @month: the gregorian month
538  * @day: the day of the gregorian month
539  * @hour: the hour of the day
540  * @minute: the minute of the hour
541  * @seconds: the second of the minute
542  *
543  * Creates a new #GstDateTime using the date and times in the gregorian calendar
544  * in the local timezone.
545  *
546  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
547  * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59.
548  *
549  * If value is -1 then all over value will be ignored. For example
550  * if @month == -1, then #GstDateTime will created only for @year. If
551  * @day == -1, then #GstDateTime will created for @year and @month and
552  * so on.
553  *
554  * Free-function: gst_date_time_unref
555  *
556  * Return value: (transfer full): the newly created #GstDateTime
557  *
558  * Since: 0.10.31
559  */
560 GstDateTime *
561 gst_date_time_new_local_time (gint year, gint month, gint day, gint hour,
562     gint minute, gdouble seconds)
563 {
564   GstDateTime *datetime;
565   DateTimeFields fields;
566
567   g_return_val_if_fail (year > 0 && year <= 9999, NULL);
568   g_return_val_if_fail ((month > 0 && month <= 12) || month == -1, NULL);
569   g_return_val_if_fail ((day > 0 && day <= 31) || day == -1, NULL);
570   g_return_val_if_fail ((hour >= 0 && hour < 24) || hour == -1, NULL);
571   g_return_val_if_fail ((minute >= 0 && minute < 60) || minute == -1, NULL);
572   g_return_val_if_fail ((seconds >= 0 && seconds < 60) || seconds == -1, NULL);
573
574   fields = gst_date_time_check_fields (&year, &month, &day,
575       &hour, &minute, &seconds);
576
577   datetime = gst_date_time_new_from_gdatetime (g_date_time_new_local (year,
578           month, day, hour, minute, seconds));
579
580   datetime->fields = fields;
581   return datetime;
582 }
583
584 /**
585  * gst_date_time_new_now_local_time:
586  *
587  * Creates a new #GstDateTime representing the current date and time.
588  *
589  * Free-function: gst_date_time_unref
590  *
591  * Return value: (transfer full): the newly created #GstDateTime which should
592  *     be freed with gst_date_time_unref().
593  *
594  * Since: 0.10.31
595  */
596 GstDateTime *
597 gst_date_time_new_now_local_time (void)
598 {
599   GstDateTime *datetime;
600
601   datetime = gst_date_time_new_from_gdatetime (g_date_time_new_now_local ());
602   datetime->fields = HAS_YMD_HMS;
603   return datetime;
604 }
605
606 /**
607  * gst_date_time_new_now_utc:
608  *
609  * Creates a new #GstDateTime that represents the current instant at Universal
610  * coordinated time.
611  *
612  * Free-function: gst_date_time_unref
613  *
614  * Return value: (transfer full): the newly created #GstDateTime which should
615  *   be freed with gst_date_time_unref().
616  *
617  * Since: 0.10.31
618  */
619 GstDateTime *
620 gst_date_time_new_now_utc (void)
621 {
622   GstDateTime *datetime;
623
624   datetime = gst_date_time_new_from_gdatetime (g_date_time_new_now_utc ());
625   datetime->fields = HAS_YMD_HMS;
626   return datetime;
627 }
628
629 gint
630 priv_gst_date_time_compare (gconstpointer dt1, gconstpointer dt2)
631 {
632   const GstDateTime *datetime1 = dt1;
633   const GstDateTime *datetime2 = dt2;
634   return g_date_time_compare (datetime1->datetime, datetime2->datetime);
635 }
636
637 /**
638  * gst_date_time_new:
639  * @tzoffset: Offset from UTC in hours.
640  * @year: the gregorian year
641  * @month: the gregorian month
642  * @day: the day of the gregorian month
643  * @hour: the hour of the day
644  * @minute: the minute of the hour
645  * @seconds: the second of the minute
646  *
647  * Creates a new #GstDateTime using the date and times in the gregorian calendar
648  * in the supplied timezone.
649  *
650  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
651  * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59.
652  *
653  * Note that @tzoffset is a float and was chosen so for being able to handle
654  * some fractional timezones, while it still keeps the readability of
655  * represeting it in hours for most timezones.
656  *
657  * If value is -1 then all over value will be ignored. For example
658  * if @month == -1, then #GstDateTime will created only for @year. If
659  * @day == -1, then #GstDateTime will created for @year and @month and
660  * so on.
661  *
662  * Free-function: gst_date_time_unref
663  *
664  * Return value: (transfer full): the newly created #GstDateTime
665  *
666  * Since: 0.10.31
667  */
668 GstDateTime *
669 gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
670     gint minute, gdouble seconds)
671 {
672   gchar buf[6];
673   GTimeZone *tz;
674   GDateTime *dt;
675   GstDateTime *datetime;
676   gint tzhour, tzminute;
677   DateTimeFields fields;
678
679   g_return_val_if_fail (year > 0 && year <= 9999, NULL);
680   g_return_val_if_fail ((month > 0 && month <= 12) || month == -1, NULL);
681   g_return_val_if_fail ((day > 0 && day <= 31) || day == -1, NULL);
682   g_return_val_if_fail ((hour >= 0 && hour < 24) || hour == -1, NULL);
683   g_return_val_if_fail ((minute >= 0 && minute < 60) || minute == -1, NULL);
684   g_return_val_if_fail ((seconds >= 0 && seconds < 60) || seconds == -1, NULL);
685   g_return_val_if_fail (tzoffset >= -12.0 && tzoffset <= 12.0, NULL);
686
687   tzhour = (gint) ABS (tzoffset);
688   tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60);
689
690   g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour,
691       tzminute);
692
693   tz = g_time_zone_new (buf);
694
695   fields = gst_date_time_check_fields (&year, &month, &day,
696       &hour, &minute, &seconds);
697
698   dt = g_date_time_new (tz, year, month, day, hour, minute, seconds);
699   g_time_zone_unref (tz);
700
701   datetime = gst_date_time_new_from_gdatetime (dt);
702   datetime->fields = fields;
703
704   return datetime;
705 }
706
707 static void
708 gst_date_time_free (GstDateTime * datetime)
709 {
710   g_date_time_unref (datetime->datetime);
711   g_slice_free (GstDateTime, datetime);
712 }
713
714 /**
715  * gst_date_time_ref:
716  * @datetime: a #GstDateTime
717  *
718  * Atomically increments the reference count of @datetime by one.
719  *
720  * Return value: (transfer full): the reference @datetime
721  *
722  * Since: 0.10.31
723  */
724 GstDateTime *
725 gst_date_time_ref (GstDateTime * datetime)
726 {
727   g_return_val_if_fail (datetime != NULL, NULL);
728   g_return_val_if_fail (datetime->ref_count > 0, NULL);
729   g_atomic_int_inc (&datetime->ref_count);
730   return datetime;
731 }
732
733 /**
734  * gst_date_time_unref:
735  * @datetime: (transfer full): a #GstDateTime
736  *
737  * Atomically decrements the reference count of @datetime by one.  When the
738  * reference count reaches zero, the structure is freed.
739  *
740  * Since: 0.10.31
741  */
742 void
743 gst_date_time_unref (GstDateTime * datetime)
744 {
745   g_return_if_fail (datetime != NULL);
746   g_return_if_fail (datetime->ref_count > 0);
747
748   if (g_atomic_int_dec_and_test (&datetime->ref_count))
749     gst_date_time_free (datetime);
750 }