gmyth/src/gmyth_util.c
author rosfran
Sat Mar 03 00:01:34 2007 +0000 (2007-03-03)
branchtrunk
changeset 384 060c3ceb43a0
parent 349 7005e696052c
child 388 7c2dde09dc8a
permissions -rw-r--r--
[svn r389] Some improvements on recorded file detection.
     1 /**
     2 * GMyth Library
     3 *
     4 * @file gmyth/gmyth_util.c
     5 * 
     6 * @brief <p> This component provides utility functions.
     7 * 
     8 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
     9 * @author Hallyson Luiz de Morais Melo <hallyson.melo@indt.org.br>
    10 *
    11 *//*
    12 * 
    13 * This program is free software; you can redistribute it and/or modify
    14 * it under the terms of the GNU Lesser General Public License as published by
    15 * the Free Software Foundation; either version 2 of the License, or
    16 * (at your option) any later version.
    17 *
    18 * This program is distributed in the hope that it will be useful,
    19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
    20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    21 * GNU General Public License for more details.
    22 *
    23 * You should have received a copy of the GNU Lesser General Public License
    24 * along with this program; if not, write to the Free Software
    25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    26 */
    27  
    28 #ifdef HAVE_CONFIG_H
    29 #include "config.h"
    30 #endif
    31 
    32 #define _XOPEN_SOURCE
    33 #define _XOPEN_SOURCE_EXTENDED
    34 #define __USE_MISC
    35 
    36 #include <glib.h>
    37 #include <glib/gprintf.h>
    38 #include <time.h>
    39 #include <sys/time.h>
    40 #include <sys/timex.h>
    41 
    42 #include "gmyth.h"
    43 
    44 #if !GLIB_CHECK_VERSION (2, 10, 0)
    45 gchar *
    46 g_time_val_to_iso8601 (GTimeVal *time_);
    47 gboolean
    48 g_time_val_from_iso8601 (const gchar *iso_date,
    49                          GTimeVal    *time_);
    50 void
    51 g_date_set_time_val (GDate    *date,
    52              GTimeVal *timeval);
    53 
    54 #endif
    55 
    56 static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
    57 
    58 /** Converts a time_t struct in a GString at ISO standard format 
    59  * (e.g. 2006-07-20T09:56:41).
    60  * 
    61  * The returned GString memory should be deallocated from 
    62  * the calling function.
    63  *
    64  * @param time_value the time value to be converted
    65  * @return GString* the converted isoformat string 
    66  */
    67 GString*
    68 gmyth_util_time_to_isoformat (time_t time_value)
    69 {
    70 	struct tm tm_time;
    71 	GString *result;
    72 	
    73 	g_static_mutex_lock ( &mutex );
    74 	
    75 	if (localtime_r(&time_value, &tm_time) == NULL) {
    76 	    g_static_mutex_unlock ( &mutex );
    77 	    g_warning ("gmyth_util_time_to_isoformat convertion error!\n");
    78             return NULL;
    79 	}
    80 	
    81 	result = g_string_sized_new(20);
    82 	g_string_printf(result, "%04d-%02d-%02dT%02d:%02d:%02d",
    83 		tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
    84 		tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
    85 		
    86 	gmyth_debug( "Result (ISO 8601) = %s", result->str );
    87 
    88 	g_static_mutex_unlock ( &mutex );
    89 	
    90 	return result;
    91 }
    92 
    93 /** Converts a time_t struct in a GString at ISO standard format 
    94  * (e.g. 2006-07-20T09:56:41).
    95  * 
    96  * The returned GString memory should be deallocated from 
    97  * the calling function.
    98  *
    99  * @param time_value the GTimeValue to be converted
   100  * @return GString* the converted isoformat string 
   101  */
   102 gchar*
   103 gmyth_util_time_to_isoformat_from_time_val_fmt ( const gchar *fmt_string, const GTimeVal* time_val )
   104 {
   105 	gchar *result = NULL;
   106 	struct tm *tm_time = NULL;
   107 	
   108 	gint buffer_len = 0;
   109 	
   110 	g_return_val_if_fail( fmt_string != NULL, NULL );
   111 		
   112 	g_return_val_if_fail( time_val != NULL, NULL );
   113  
   114 	time_t time = time_val->tv_sec;// + (gint)( time_val->tv_usec / G_USEC_PER_SEC );
   115 
   116 	tm_time = g_malloc0( sizeof(struct tm) );
   117 
   118 	g_static_mutex_lock ( &mutex );
   119 	
   120 	if ( NULL == localtime_r( &time, tm_time ) ) {
   121 		g_warning ("gmyth_util_time_to_isoformat convertion error!\n");
   122 	}	else {
   123 		// we first check the return of strftime to allocate a buffer of the correct size
   124 	  buffer_len = strftime( NULL, SSIZE_MAX, fmt_string, tm_time );
   125 	  if ( buffer_len > 0 ) {
   126 	    result = g_malloc0( buffer_len + 1 );
   127 	    if( result == NULL ){
   128 				g_static_mutex_unlock ( &mutex );
   129 				g_warning ("gmyth_util_time_to_isoformat convertion error!\n");
   130 				return NULL;
   131 	    }
   132 	    strftime( result, buffer_len + 1, fmt_string, tm_time );
   133 	    gmyth_debug( "Dateline (ISO result): %s", result );
   134 	  }
   135 		
   136 	}
   137 	
   138 	gmyth_debug( "Result (strftime) = %s", result );
   139 	
   140 	//strptime( result, "%Y-%m-%dT%H:%M:%SZ", tm_time ); 
   141 	
   142 	//strftime( result, strlen(result), fmt_string, tm_time );
   143 	
   144 	g_static_mutex_unlock ( &mutex );
   145 	
   146 	gmyth_debug( "Result (ISO 8601) = %s", result  );
   147 	
   148 	return result;	
   149 		
   150 }
   151 
   152 /** Converts a time_t struct in a GString at ISO standard format 
   153  * (e.g. 2006-07-20 09:56:41).
   154  * 
   155  * The returned GString memory should be deallocated from 
   156  * the calling function.
   157  *
   158  * @param time_value the GTimeValue to be converted
   159  * @return GString* the converted isoformat string 
   160  */
   161 gchar*
   162 gmyth_util_time_to_isoformat_from_time_val ( const GTimeVal* time )
   163 {
   164 	gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%d %H:%M:%S", time );
   165 	//result[10] = ' ';
   166 	//result[ strlen(result) - 1] = '\0';
   167 	
   168 	return result;	
   169 }
   170 
   171 /** Converts a time_t struct in a GString at ISO standard format 2 
   172  * (e.g. 2006-07-20T09:56:41).
   173  * 
   174  * The returned GString memory should be deallocated from 
   175  * the calling function.
   176  *
   177  * @param time_value the GTimeValue to be converted
   178  * @return GString* the converted isoformat string 
   179  */
   180 gchar*
   181 gmyth_util_time_to_mythformat_from_time_val ( const GTimeVal* time )
   182 {
   183 	gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%dT%H:%M:%S", time );
   184 	return result;	
   185 }
   186 
   187 /** Converts a time_t struct in a GString at ISO standard format 
   188  * (e.g. 2006-07-20T09:56:41).
   189  * 
   190  * The returned GString memory should be deallocated from 
   191  * the calling function.
   192  *
   193  * @param time_value the GTimeValue to be converted
   194  * @return GString* the converted isoformat string 
   195  */
   196 gchar*
   197 gmyth_util_time_to_string_only_date ( const GTimeVal* time )
   198 {
   199 	gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%Y-%m-%d", time );
   200 	//result[10] = ' ';
   201 	//result[ strlen(result) - 1] = '\0';
   202 	return result;
   203 }
   204 
   205 /** Converts a time_t struct in a GString at ISO standard format 
   206  * (e.g. 2006-07-20T09:56:41).
   207  * 
   208  * The returned GString memory should be deallocated from 
   209  * the calling function.
   210  *
   211  * @param time_value the GTimeValue to be converted
   212  * @return GString* the converted isoformat string 
   213  */
   214 gchar*
   215 gmyth_util_time_to_string_only_time ( const GTimeVal* time )
   216 {
   217 	gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt( "%H:%M:%S", time );	 
   218 	//result[10] = ' ';
   219 	//result[ strlen(result) - 1] = '\0';
   220 	return result;
   221 }
   222 
   223 /** Converts a time_t struct in a GString to the following 
   224  * format (e.g. 2006-07-20 09:56:41).
   225  * 
   226  * The returned GString memory should be deallocated from 
   227  * the calling function.
   228  *
   229  * @param time_value the time value to be converted
   230  * @return GString* the converted string 
   231  */
   232 GString*
   233 gmyth_util_time_to_string (time_t time_value)
   234 {
   235 	GString *result = gmyth_util_time_to_isoformat (time_value);
   236 	result->str[10] = ' ';	
   237 	result->str[ strlen(result->str) - 1] = '\0';
   238 
   239 	return result;
   240 }
   241 
   242 /** Converts a time_t struct in a GString to the following 
   243  * format (e.g. 2006-07-20 09:56:41).
   244  * 
   245  * The returned GString memory should be deallocated from 
   246  * the calling function.
   247  *
   248  * @param time_value the time value to be converted
   249  * @return GString* the converted string 
   250  */
   251 gchar*
   252 gmyth_util_time_to_string_from_time_val ( const GTimeVal *time_val )
   253 {
   254 	gchar *result = gmyth_util_time_to_isoformat_from_time_val_fmt ( "%Y-%m-%d %H:%M:%S", time_val );
   255 	//result[10] = ' ';
   256 
   257 	return result;
   258 }
   259 
   260 /** Converts a GString in the following format 
   261  * (e.g. 2006-07-20 09:56:41) to a time_t struct.
   262  * 
   263  * @param time_str the string to be converted
   264  * @return time_t the time converted value
   265  */
   266 time_t
   267 gmyth_util_string_to_time (GString* time_str)
   268 {
   269 	gint year, month, day, hour, min, sec;
   270     
   271 	gmyth_debug( "[%s] time_str = %s. [%s]", __FUNCTION__, time_str != NULL ? 
   272 					time_str->str : "[time string is NULL!]", time_str->str );
   273 
   274 	if ( sscanf (time_str->str, "%04d-%02d-%02d %02d:%02d:%02d",
   275 			&year, &month, &day, &hour, &min, &sec) < 3 ) {
   276 		g_warning ("GMythUtil: isoformat_to_time converter error!\n");
   277 		return 0;
   278 	}
   279 	
   280 	g_static_mutex_lock ( &mutex );
   281 	
   282 	struct tm* tm_time = g_malloc0( sizeof(struct tm) );
   283 	tm_time->tm_year = year - 1900;
   284 	tm_time->tm_mon = month - 1;
   285 	tm_time->tm_mday = day;
   286 	tm_time->tm_hour = hour;
   287 	tm_time->tm_min = min;
   288 	tm_time->tm_sec = sec;
   289 	
   290 	g_static_mutex_unlock ( &mutex );
   291 	
   292 	return mktime( tm_time );
   293 }
   294 
   295 /** Converts a GString in the following format 
   296  * (e.g. 2006-07-20 09:56:41) to a time_t struct.
   297  * 
   298  * @param time_str the string to be converted
   299  * @return time_t the time converted value
   300  */
   301 struct tm*
   302 gmyth_util_time_val_to_date ( const GTimeVal* time )
   303 {
   304 	struct tm *date = g_malloc0( sizeof( struct tm ) );
   305 	time_t time_micros = time->tv_sec;// + (gint)( time->tv_usec / G_USEC_PER_SEC );
   306     
   307   if ( NULL == date ) { 
   308 		g_warning ( "GMythUtil: GDate *gmyth_util_time_val_to_date (GTimeVal* time) - converter error!\n" );
   309 		return NULL;
   310 	}
   311 	
   312 	if ( NULL == localtime_r( &time_micros, date ) ) {
   313 		g_warning ( "gmyth_util_time_to_isoformat convertion error!\n" );
   314 		return NULL;
   315 	}
   316 
   317 	gmyth_debug( "Converted from GTimeVal == %s to GDate", asctime( date ) );
   318 	
   319 	return date;
   320 }
   321 
   322 /** Converts a GString in the following format 
   323  * (e.g. 2006-07-20 09:56:41) to a time_t struct.
   324  * 
   325  * @param time_str the string to be converted
   326  * @return time_t the time converted value
   327  */
   328 GTimeVal*
   329 gmyth_util_string_to_time_val_fmt ( const gchar *fmt_string, const gchar* time_str )
   330 {
   331 	GTimeVal *time = g_new0( GTimeVal, 1 );
   332 	struct tm* tm_time = NULL;
   333 	time_t time_micros;
   334 	gchar* result;
   335     
   336 	gmyth_debug( "[%s] time_str = %s. [%s]", time_str, time_str != NULL ? 
   337                  time_str : "[time string is NULL!]", time_str );
   338     
   339 	if ( NULL == time_str ) 
   340       { 
   341 		g_warning ("GMythUtil: isoformat_to_time converter error!\n");
   342 		return NULL;
   343       }
   344 	
   345 	g_static_mutex_lock ( &mutex );
   346 	
   347 	tm_time = g_malloc0( sizeof(struct tm) );
   348     
   349 	/* we first check the return of strftime to allocate a buffer of the correct size */
   350     result = strptime( time_str, "%Y-%m-%dT%H:%M:%S", tm_time );
   351     if ( NULL == result ) {
   352       /* we first check the return of strftime to allocate a buffer of the correct size */
   353 	  result = strptime( time_str, "%Y-%m-%dT%H:%M:%SZ", tm_time );
   354 	  if ( NULL == result ) {
   355 	  	/* we first check the return of strftime to allocate a buffer of the correct size */
   356         result = strptime( time_str, "%Y-%m-%d %H:%M:%S", tm_time );
   357         if ( NULL == result) {
   358           result = strptime( time_str, "%Y-%m-%dT%H:%M", tm_time );
   359           if ( NULL == result ) {
   360             g_static_mutex_unlock ( &mutex );
   361             gmyth_debug( "Dateline (ISO result): %s", result );
   362             g_free(tm_time);
   363             return NULL;
   364             //goto done;	    
   365           }
   366         }
   367 	  }
   368     }
   369     
   370     time_micros = mktime( tm_time );
   371     
   372     time->tv_sec = time_micros; // + (gint)( time_val->tv_usec / G_USEC_PER_SEC );
   373     
   374     gmyth_debug( "After mktime call... = %s", asctime(tm_time) );
   375     
   376     g_static_mutex_unlock ( &mutex );
   377     
   378     return time;
   379 }
   380 
   381 /** Converts a GString in the following format 
   382  * (e.g. 2006-07-20 09:56:41) to a time_t struct.
   383  * 
   384  * @param time_str the string to be converted
   385  * @return time_t the time converted value
   386  */
   387 GTimeVal*
   388 gmyth_util_string_to_time_val ( const gchar* time_str )
   389 {
   390 	GTimeVal *time = gmyth_util_string_to_time_val_fmt ( "%Y-%m-%d %H:%M:%S", time_str );	
   391 	
   392 	return time;
   393 }
   394 
   395 /** Decodes a long long variable from the string list
   396  * format of the myhtprotocol.
   397  * 
   398  * @param strlist the string list of mythprotocol values
   399  * @param offset  the list node offset of the long long variable
   400  * @return gint64  the long long converted value
   401  */
   402 gint64
   403 gmyth_util_decode_long_long(GMythStringList *strlist, guint offset) 
   404 {
   405 
   406 	gint64 ret_value = 0LL;
   407 
   408 	g_return_val_if_fail( strlist != NULL, ret_value );
   409 
   410 	if ( offset > gmyth_string_list_length( strlist ))
   411 		g_printerr( "[%s] Offset is greater than the Stringlist (offset = %d)!\n", 
   412                     __FUNCTION__, offset );
   413     
   414 	g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value );
   415 
   416 	gint l1 = gmyth_string_list_get_int( strlist, offset );
   417 	gint l2 = gmyth_string_list_get_int( strlist, offset + 1 );
   418 
   419 	ret_value = (l2 /*& 0xffffffffLL*/) | ( (gint64)l1 << 32 );
   420 
   421 	return ret_value;
   422 
   423 }
   424 
   425 gboolean
   426 gmyth_util_file_exists (GMythBackendInfo *backend_info, const gchar* filename)
   427 {
   428     GMythSocket *socket;
   429     gboolean res;
   430     
   431     socket = gmyth_socket_new ();
   432     res = gmyth_socket_connect_to_backend (socket, backend_info->hostname,
   433 		    backend_info->port, TRUE);
   434 
   435     if (res == TRUE) {
   436         GMythStringList *slist;
   437         GMythProgramInfo *program = NULL;
   438 
   439         program = gmyth_program_info_new();
   440         program->pathname = g_string_new (filename);
   441 
   442         slist = gmyth_string_list_new ();
   443         gmyth_string_list_append_char_array (slist, "QUERY_CHECKFILE");
   444 
   445         gmyth_program_info_to_string_list (program, slist);
   446 
   447         gmyth_socket_sendreceive_stringlist (socket, slist);
   448 
   449         res = (gmyth_string_list_get_int (slist, 0) == 1);
   450     
   451         g_object_unref (program);
   452 
   453         g_object_unref (slist);
   454 
   455         gmyth_socket_close_connection (socket);
   456     }
   457     g_object_unref (socket);
   458     return res;    
   459 }
   460 
   461 gboolean
   462 gmyth_util_file_exists_and_get_remote_dir (GMythBackendInfo *backend_info, 
   463 						const gchar* filename, gchar** current_dir)
   464 {
   465     GMythSocket *socket;
   466     gboolean res;
   467     
   468     *current_dir = NULL;
   469     
   470     socket = gmyth_socket_new ();
   471     res = gmyth_socket_connect_to_backend (socket, backend_info->hostname,
   472 		    backend_info->port, TRUE);
   473 
   474     if (res == TRUE) {
   475         GMythStringList *slist;
   476         GMythProgramInfo *program = NULL;
   477 
   478         program = gmyth_program_info_new();
   479         program->pathname = g_string_new (filename);
   480 
   481         slist = gmyth_string_list_new ();
   482         gmyth_string_list_append_char_array (slist, "QUERY_CHECKFILE");
   483 
   484         gmyth_program_info_to_string_list (program, slist);
   485 
   486         gmyth_socket_sendreceive_stringlist (socket, slist);
   487 
   488         res = (gmyth_string_list_get_int (slist, 0) == 1);
   489         
   490         if ( ( gmyth_string_list_length( slist ) > 1 ) && 
   491         			gmyth_string_list_get_char_array (slist, 1) != NULL )
   492         	*current_dir = g_strdup( gmyth_string_list_get_char_array (slist, 1) );
   493     
   494         g_object_unref (program);
   495 
   496         g_object_unref (slist);
   497 
   498         gmyth_socket_close_connection (socket);
   499     }
   500     g_object_unref (socket);
   501     return res;    
   502 }
   503 
   504 gchar*
   505 gmyth_util_create_filename( const gint chan_id, const GTimeVal* start_time )
   506 { 
   507 	gchar* basename = NULL;
   508 	
   509 	g_return_val_if_fail( start_time != NULL, NULL );
   510 	
   511   gchar *isodate = gmyth_util_time_to_isoformat_from_time_val_fmt ( "%Y%m%d%H%M%S", 
   512   				start_time );
   513 
   514 	basename = g_strdup_printf( "%d_%s", chan_id, isodate );
   515 
   516 	gmyth_debug ("Basename (from chan_id and start_time): %s", basename);
   517 
   518 	if (isodate)
   519   	g_free(isodate);
   520   
   521 	return basename;
   522 }
   523 
   524 #if !GLIB_CHECK_VERSION (2, 10, 0)
   525 
   526 /* Hacked from glib 2.10 <gtime.c> */
   527 
   528 static time_t
   529 mktime_utc (struct tm *tm)
   530 {
   531   time_t retval;
   532   
   533 #ifndef HAVE_TIMEGM
   534   static const gint days_before[] =
   535   {
   536     0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
   537   };
   538 #endif
   539 
   540 #ifndef HAVE_TIMEGM
   541   if (tm->tm_mon < 0 || tm->tm_mon > 11)
   542     return (time_t) -1;
   543 
   544   retval = (tm->tm_year - 70) * 365;
   545   retval += (tm->tm_year - 68) / 4;
   546   retval += days_before[tm->tm_mon] + tm->tm_mday - 1;
   547   
   548   if (tm->tm_year % 4 == 0 && tm->tm_mon < 2)
   549     retval -= 1;
   550   
   551   retval = ((((retval * 24) + tm->tm_hour) * 60) + tm->tm_min) * 60 + tm->tm_sec;
   552 #else
   553   retval = timegm (tm);
   554 #endif /* !HAVE_TIMEGM */
   555   
   556   return retval;
   557 }
   558 
   559 gboolean
   560 g_time_val_from_iso8601 (const gchar *iso_date,
   561                          GTimeVal    *time_)
   562 {
   563   struct tm tm;
   564   long val;
   565 
   566   g_return_val_if_fail (iso_date != NULL, FALSE);
   567   g_return_val_if_fail (time_ != NULL, FALSE);
   568 
   569   val = strtoul (iso_date, (char **)&iso_date, 10);
   570   if (*iso_date == '-')
   571     {
   572       /* YYYY-MM-DD */
   573       tm.tm_year = val - 1900;
   574       iso_date++;
   575       tm.tm_mon = strtoul (iso_date, (char **)&iso_date, 10) - 1;
   576       
   577       if (*iso_date++ != '-')
   578         return FALSE;
   579       
   580       tm.tm_mday = strtoul (iso_date, (char **)&iso_date, 10);
   581     }
   582   else
   583     {
   584       /* YYYYMMDD */
   585       tm.tm_mday = val % 100;
   586       tm.tm_mon = (val % 10000) / 100 - 1;
   587       tm.tm_year = val / 10000 - 1900;
   588     }
   589 
   590   if (*iso_date++ != 'T')
   591     return FALSE;
   592   
   593   val = strtoul (iso_date, (char **)&iso_date, 10);
   594   if (*iso_date == ':')
   595     {
   596       /* hh:mm:ss */
   597       tm.tm_hour = val;
   598       iso_date++;
   599       tm.tm_min = strtoul (iso_date, (char **)&iso_date, 10);
   600       
   601       if (*iso_date++ != ':')
   602         return FALSE;
   603       
   604       tm.tm_sec = strtoul (iso_date, (char **)&iso_date, 10);
   605     }
   606   else
   607     {
   608       /* hhmmss */
   609       tm.tm_sec = val % 100;
   610       tm.tm_min = (val % 10000) / 100;
   611       tm.tm_hour = val / 10000;
   612     }
   613 
   614   time_->tv_sec = mktime_utc (&tm);
   615   time_->tv_usec = 1;
   616   
   617   if (*iso_date == '.')
   618     time_->tv_usec = strtoul (iso_date + 1, (char **)&iso_date, 10);
   619     
   620   if (*iso_date == '+' || *iso_date == '-')
   621     {
   622       gint sign = (*iso_date == '+') ? -1 : 1;
   623       
   624       val = 60 * strtoul (iso_date + 1, (char **)&iso_date, 10);
   625       
   626       if (*iso_date == ':')
   627     val = 60 * val + strtoul (iso_date + 1, NULL, 10);
   628       else
   629         val = 60 * (val / 100) + (val % 100);
   630 
   631       time_->tv_sec += (time_t) (val * sign);
   632     }
   633 
   634   return TRUE;
   635 }
   636 
   637 
   638 gchar *
   639 g_time_val_to_iso8601 (GTimeVal *time_)
   640 {
   641   gchar *retval;
   642 
   643   g_return_val_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC, NULL);
   644 
   645 #define ISO_8601_LEN    21
   646 #define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ"
   647   retval = g_new0 (gchar, ISO_8601_LEN + 1);
   648   
   649   strftime (retval, ISO_8601_LEN,
   650         ISO_8601_FORMAT,
   651         gmtime (&(time_->tv_sec)));
   652   
   653   return retval;
   654 }
   655 
   656 
   657 /* Hacked from glib 2.10 <gdate.c> */
   658 
   659 void         
   660 g_date_set_time_t (GDate *date,
   661            time_t timet)
   662 {
   663   struct tm tm;
   664   
   665   g_return_if_fail (date != NULL);
   666   
   667 #ifdef HAVE_LOCALTIME_R
   668   localtime_r (&timet, &tm);
   669 #else
   670   {
   671     struct tm *ptm = localtime (&timet);
   672 
   673     if (ptm == NULL)
   674       {
   675     /* Happens at least in Microsoft's C library if you pass a
   676      * negative time_t. Use 2000-01-01 as default date.
   677      */
   678 #ifndef G_DISABLE_CHECKS
   679     g_return_if_fail_warning (G_LOG_DOMAIN, "g_date_set_time", "ptm != NULL");
   680 #endif
   681 
   682     tm.tm_mon = 0;
   683     tm.tm_mday = 1;
   684     tm.tm_year = 100;
   685       }
   686     else
   687       memcpy ((void *) &tm, (void *) ptm, sizeof(struct tm));
   688   }
   689 #endif
   690   
   691   date->julian = FALSE;
   692   
   693   date->month = tm.tm_mon + 1;
   694   date->day   = tm.tm_mday;
   695   date->year  = tm.tm_year + 1900;
   696   
   697   g_return_if_fail (g_date_valid_dmy (date->day, date->month, date->year));
   698   
   699   date->dmy    = TRUE;
   700 }
   701 
   702 
   703 void
   704 g_date_set_time_val (GDate    *date,
   705              GTimeVal *timeval)
   706 {
   707   g_date_set_time_t (date, (time_t) timeval->tv_sec);
   708 }
   709 
   710 
   711 
   712 
   713 #endif