datetime: remove fallback code for old GLibs
[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 struct _GstDateTime
53 {
54   GDateTime *datetime;
55
56   volatile gint ref_count;
57 };
58
59 static GstDateTime *
60 gst_date_time_new_from_gdatetime (GDateTime * dt)
61 {
62   GstDateTime *gst_dt;
63
64   if (!dt)
65     return NULL;
66
67   gst_dt = g_slice_new (GstDateTime);
68   gst_dt->datetime = dt;
69   gst_dt->ref_count = 1;
70   return gst_dt;
71 }
72
73 /**
74  * gst_date_time_get_year:
75  * @datetime: a #GstDateTime
76  *
77  * Returns the year of this #GstDateTime
78  *
79  * Return value: The year of this #GstDateTime
80  * Since: 0.10.31
81  */
82 gint
83 gst_date_time_get_year (const GstDateTime * datetime)
84 {
85   return g_date_time_get_year (datetime->datetime);
86 }
87
88 /**
89  * gst_date_time_get_month:
90  * @datetime: a #GstDateTime
91  *
92  * Returns the month of this #GstDateTime. January is 1, February is 2, etc..
93  *
94  * Return value: The month of this #GstDateTime
95  * Since: 0.10.31
96  */
97 gint
98 gst_date_time_get_month (const GstDateTime * datetime)
99 {
100   return g_date_time_get_month (datetime->datetime);
101 }
102
103 /**
104  * gst_date_time_get_day:
105  * @datetime: a #GstDateTime
106  *
107  * Returns the day of this #GstDateTime.
108  *
109  * Return value: The day of this #GstDateTime
110  * Since: 0.10.31
111  */
112 gint
113 gst_date_time_get_day (const GstDateTime * datetime)
114 {
115   return g_date_time_get_day_of_month (datetime->datetime);
116 }
117
118 /**
119  * gst_date_time_get_hour:
120  * @datetime: a #GstDateTime
121  *
122  * Retrieves the hour of the day represented by @datetime in the gregorian
123  * calendar. The return is in the range of 0 to 23.
124  *
125  * Return value: the hour of the day
126  *
127  * Since: 0.10.31
128  */
129 gint
130 gst_date_time_get_hour (const GstDateTime * datetime)
131 {
132   return g_date_time_get_hour (datetime->datetime);
133 }
134
135 /**
136  * gst_date_time_get_minute:
137  * @datetime: a #GstDateTime
138  *
139  * Retrieves the minute of the hour represented by @datetime in the gregorian
140  * calendar.
141  *
142  * Return value: the minute of the hour
143  *
144  * Since: 0.10.31
145  */
146 gint
147 gst_date_time_get_minute (const GstDateTime * datetime)
148 {
149   return g_date_time_get_minute (datetime->datetime);
150 }
151
152 /**
153  * gst_date_time_get_second:
154  * @datetime: a #GstDateTime
155  *
156  * Retrieves the second of the minute represented by @datetime in the gregorian
157  * calendar.
158  *
159  * Return value: the second represented by @datetime
160  *
161  * Since: 0.10.31
162  */
163 gint
164 gst_date_time_get_second (const GstDateTime * datetime)
165 {
166   return g_date_time_get_second (datetime->datetime);
167 }
168
169 /**
170  * gst_date_time_get_microsecond:
171  * @datetime: a #GstDateTime
172  *
173  * Retrieves the fractional part of the seconds in microseconds represented by
174  * @datetime in the gregorian calendar.
175  *
176  * Return value: the microsecond of the second
177  *
178  * Since: 0.10.31
179  */
180 gint
181 gst_date_time_get_microsecond (const GstDateTime * datetime)
182 {
183   return g_date_time_get_microsecond (datetime->datetime);
184 }
185
186 /**
187  * gst_date_time_get_time_zone_offset:
188  * @datetime: a #GstDateTime
189  *
190  * Retrieves the offset from UTC in hours that the timezone specified
191  * by @datetime represents. Timezones ahead (to the east) of UTC have positive
192  * values, timezones before (to the west) of UTC have negative values.
193  * If @datetime represents UTC time, then the offset is zero.
194  *
195  * Return value: the offset from UTC in hours
196  * Since: 0.10.31
197  */
198 gfloat
199 gst_date_time_get_time_zone_offset (const GstDateTime * datetime)
200 {
201   return (g_date_time_get_utc_offset (datetime->datetime) /
202       G_USEC_PER_SEC) / 3600.0;
203 }
204
205 /**
206  * gst_date_time_new_from_unix_epoch_local_time:
207  * @secs: seconds from the Unix epoch
208  *
209  * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
210  * @secs. The #GstDateTime is in the local timezone.
211  *
212  * Free-function: gst_date_time_unref
213  *
214  * Return value: (transfer full): the newly created #GstDateTime
215  *
216  * Since: 0.10.31
217  */
218 GstDateTime *
219 gst_date_time_new_from_unix_epoch_local_time (gint64 secs)
220 {
221   return
222       gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_local (secs));
223 }
224
225 /**
226  * gst_date_time_new_from_unix_epoch_utc:
227  * @secs: seconds from the Unix epoch
228  *
229  * Creates a new #GstDateTime using the time since Jan 1, 1970 specified by
230  * @secs. The #GstDateTime is in the UTC timezone.
231  *
232  * Free-function: gst_date_time_unref
233  *
234  * Return value: (transfer full): the newly created #GstDateTime
235  *
236  * Since: 0.10.31
237  */
238 GstDateTime *
239 gst_date_time_new_from_unix_epoch_utc (gint64 secs)
240 {
241   return
242       gst_date_time_new_from_gdatetime (g_date_time_new_from_unix_utc (secs));
243 }
244
245 /**
246  * gst_date_time_new_local_time:
247  * @year: the gregorian year
248  * @month: the gregorian month
249  * @day: the day of the gregorian month
250  * @hour: the hour of the day
251  * @minute: the minute of the hour
252  * @seconds: the second of the minute
253  *
254  * Creates a new #GstDateTime using the date and times in the gregorian calendar
255  * in the local timezone.
256  *
257  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
258  * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59.
259  *
260  * Free-function: gst_date_time_unref
261  *
262  * Return value: (transfer full): the newly created #GstDateTime
263  *
264  * Since: 0.10.31
265  */
266 GstDateTime *
267 gst_date_time_new_local_time (gint year, gint month, gint day, gint hour,
268     gint minute, gdouble seconds)
269 {
270   return gst_date_time_new_from_gdatetime (g_date_time_new_local (year, month,
271           day, hour, minute, seconds));
272 }
273
274 /**
275  * gst_date_time_new_now_local_time:
276  *
277  * Creates a new #GstDateTime representing the current date and time.
278  *
279  * Free-function: gst_date_time_unref
280  *
281  * Return value: (transfer full): the newly created #GstDateTime which should
282  *     be freed with gst_date_time_unref().
283  *
284  * Since: 0.10.31
285  */
286 GstDateTime *
287 gst_date_time_new_now_local_time (void)
288 {
289   return gst_date_time_new_from_gdatetime (g_date_time_new_now_local ());
290 }
291
292 /**
293  * gst_date_time_new_now_utc:
294  *
295  * Creates a new #GstDateTime that represents the current instant at Universal
296  * coordinated time.
297  *
298  * Free-function: gst_date_time_unref
299  *
300  * Return value: (transfer full): the newly created #GstDateTime which should
301  *   be freed with gst_date_time_unref().
302  *
303  * Since: 0.10.31
304  */
305 GstDateTime *
306 gst_date_time_new_now_utc (void)
307 {
308   return gst_date_time_new_from_gdatetime (g_date_time_new_now_utc ());
309 }
310
311 gint
312 priv_gst_date_time_compare (gconstpointer dt1, gconstpointer dt2)
313 {
314   const GstDateTime *datetime1 = dt1;
315   const GstDateTime *datetime2 = dt2;
316   return g_date_time_compare (datetime1->datetime, datetime2->datetime);
317 }
318
319 /**
320  * gst_date_time_new:
321  * @tzoffset: Offset from UTC in hours.
322  * @year: the gregorian year
323  * @month: the gregorian month
324  * @day: the day of the gregorian month
325  * @hour: the hour of the day
326  * @minute: the minute of the hour
327  * @seconds: the second of the minute
328  *
329  * Creates a new #GstDateTime using the date and times in the gregorian calendar
330  * in the supplied timezone.
331  *
332  * @year should be from 1 to 9999, @month should be from 1 to 12, @day from
333  * 1 to 31, @hour from 0 to 23, @minutes and @seconds from 0 to 59.
334  *
335  * Note that @tzoffset is a float and was chosen so for being able to handle
336  * some fractional timezones, while it still keeps the readability of
337  * represeting it in hours for most timezones.
338  *
339  * Free-function: gst_date_time_unref
340  *
341  * Return value: (transfer full): the newly created #GstDateTime
342  *
343  * Since: 0.10.31
344  */
345 GstDateTime *
346 gst_date_time_new (gfloat tzoffset, gint year, gint month, gint day, gint hour,
347     gint minute, gdouble seconds)
348 {
349   gchar buf[6];
350   GTimeZone *tz;
351   GDateTime *dt;
352   gint tzhour, tzminute;
353
354   tzhour = (gint) ABS (tzoffset);
355   tzminute = (gint) ((ABS (tzoffset) - tzhour) * 60);
356
357   g_snprintf (buf, 6, "%c%02d%02d", tzoffset >= 0 ? '+' : '-', tzhour,
358       tzminute);
359
360   tz = g_time_zone_new (buf);
361
362   dt = g_date_time_new (tz, year, month, day, hour, minute, seconds);
363   g_time_zone_unref (tz);
364   return gst_date_time_new_from_gdatetime (dt);
365 }
366
367 static void
368 gst_date_time_free (GstDateTime * datetime)
369 {
370   g_date_time_unref (datetime->datetime);
371   g_slice_free (GstDateTime, datetime);
372 }
373
374 /**
375  * gst_date_time_ref:
376  * @datetime: a #GstDateTime
377  *
378  * Atomically increments the reference count of @datetime by one.
379  *
380  * Return value: (transfer full): the reference @datetime
381  *
382  * Since: 0.10.31
383  */
384 GstDateTime *
385 gst_date_time_ref (GstDateTime * datetime)
386 {
387   g_return_val_if_fail (datetime != NULL, NULL);
388   g_return_val_if_fail (datetime->ref_count > 0, NULL);
389   g_atomic_int_inc (&datetime->ref_count);
390   return datetime;
391 }
392
393 /**
394  * gst_date_time_unref:
395  * @datetime: (transfer full): a #GstDateTime
396  *
397  * Atomically decrements the reference count of @datetime by one.  When the
398  * reference count reaches zero, the structure is freed.
399  *
400  * Since: 0.10.31
401  */
402 void
403 gst_date_time_unref (GstDateTime * datetime)
404 {
405   g_return_if_fail (datetime != NULL);
406   g_return_if_fail (datetime->ref_count > 0);
407
408   if (g_atomic_int_dec_and_test (&datetime->ref_count))
409     gst_date_time_free (datetime);
410 }