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