From: <svn...@op...> - 2010-08-16 18:44:57
|
Author: cdfrey Date: Mon Aug 16 20:44:44 2010 New Revision: 6092 URL: http://www.opensync.org/changeset/6092 Log: Added osync_time_parse_iso_timezone_diff() Modified: trunk/opensync.sym trunk/opensync/format/opensync_time.c trunk/opensync/format/opensync_time.h trunk/tests/CMakeLists.txt trunk/tests/format-tests/check_time.c Modified: trunk/opensync.sym ============================================================================== --- trunk/opensync.sym Sat Aug 14 02:24:19 2010 (r6091) +++ trunk/opensync.sym Mon Aug 16 20:44:44 2010 (r6092) @@ -676,6 +676,7 @@ osync_time_isdate osync_time_isutc osync_time_localtm2unix +osync_time_parse_iso_timezone_diff osync_time_relative2tm osync_time_sec2alarmdu osync_time_str2wday Modified: trunk/opensync/format/opensync_time.c ============================================================================== --- trunk/opensync/format/opensync_time.c Sat Aug 14 02:24:19 2010 (r6091) +++ trunk/opensync/format/opensync_time.c Mon Aug 16 20:44:44 2010 (r6092) @@ -487,6 +487,47 @@ return 0; } +int osync_time_parse_iso_timezone_diff(const char *iso_vtime, int *found, OSyncError **error) +{ + char *zonepart = NULL, *plainzone = NULL; + int hour, min, scanned, offset; + + char *timepart = strchr(iso_vtime, 'T'); + if( timepart == NULL ) { + *found = 0; + return 0; + } + + zonepart = strchr(timepart, '-'); + if( zonepart == NULL ) { + zonepart = strchr(timepart, '+'); + if( zonepart == NULL ) { + *found = 0; + return 0; + } + } + + plainzone = osync_time_timestamp_remove_dash(zonepart+1); + scanned = sscanf(plainzone, "%02d%02d", &hour, &min); + if( strlen(plainzone) != 4 || scanned != 2 ) { + *found = 0; + osync_error_set(error, OSYNC_ERROR_GENERIC, "Invalid timezone offset in ISO timestamp."); + return 0; + } + + *found = 1; + offset = (hour * 60 + min) * 60; + + // timezone offset is the same as the ISO format indicates... + // negative values are west of UTC (like Canada) and positive + // values are east of UTC (like Germany) + if( zonepart[0] == '-' ) { + offset *= -1; + } + + return offset; +} + struct tm *osync_time_tm2utc(const struct tm *ltime, int offset, OSyncError **error) { osync_trace(TRACE_ENTRY, "%s(%p, %i)", __func__, ltime, offset); Modified: trunk/opensync/format/opensync_time.h ============================================================================== --- trunk/opensync/format/opensync_time.h Sat Aug 14 02:24:19 2010 (r6091) +++ trunk/opensync/format/opensync_time.h Mon Aug 16 20:44:44 2010 (r6092) @@ -215,6 +215,25 @@ */ OSYNC_EXPORT int osync_time_timezone_diff(const struct tm *local, OSyncError **error); +/** @brief Parse an ISO 8601 timestamp string, and if a timezone offset + * exists, return an offset suitable for feeding into vtime2unix(). + * (seconds east of UTC.. i.e. east is positive, west is negative) + * + * @param iso_vtime String containing an ISO 8601 timestamp string, in the + * format of YYYYMMDDTHHMMSS-HHMM or YYYY-MM-DDTHH:MM:SS-HH:MM. + * @param found Pointer to an int. Will be set to 1 if a valid offset was + * found, or 0 if not. Not all timestamps have a timezone offset. + * If not found, 0 will also be returned as the offset. + * @param error An OSyncError struct. Always check if error is set using + * osync_error_is_set(error) before using the return value. A non- + * existing timezone offset is not an error, but a mal-formed one, + * like "-03:0" is an error. + * @return Seconds of timezone offset. On error, sets the error parameter, + * and the return value will be zero. If no offset is found in the + * string, return is zero. + */ +OSYNC_EXPORT int osync_time_parse_iso_timezone_diff(const char *iso_vtime, int *found, OSyncError **error); + /** @brief Function converts (struct tm) ltime from localtime to UTC. * Paramter offset is used as UTC offset. Note that _only_ the * following fields can be relied upon in the result: Modified: trunk/tests/CMakeLists.txt ============================================================================== --- trunk/tests/CMakeLists.txt Sat Aug 14 02:24:19 2010 (r6091) +++ trunk/tests/CMakeLists.txt Mon Aug 16 20:44:44 2010 (r6092) @@ -389,6 +389,7 @@ BUILD_CHECK_TEST( time format-tests/check_time.c ${TEST_TARGET_LIBRARIES} ) OSYNC_TESTCASE(time time_timezone_diff) +OSYNC_TESTCASE(time time_parse_iso_timezone_diff) OSYNC_TESTCASE(time time_relative2tm) OSYNC_TESTCASE(time time_unix_converters) Modified: trunk/tests/format-tests/check_time.c ============================================================================== --- trunk/tests/format-tests/check_time.c Sat Aug 14 02:24:19 2010 (r6091) +++ trunk/tests/format-tests/check_time.c Mon Aug 16 20:44:44 2010 (r6092) @@ -60,6 +60,56 @@ } END_TEST +START_TEST (time_parse_iso_timezone_diff) +{ + OSyncError *error = NULL; + int offset, found; + + // Not found + offset = osync_time_parse_iso_timezone_diff( + "20100810T001500Z", &found, &error); + fail_unless(offset == 0 && found == 0 && error == NULL, NULL); + + // Not found with dashes + offset = osync_time_parse_iso_timezone_diff( + "2010-08-10T00:15:00Z", &found, &error); + fail_unless(offset == 0 && found == 0 && error == NULL, NULL); + + // Found, with no separators + offset = osync_time_parse_iso_timezone_diff( + "20100810T001500-0300", &found, &error); + fail_unless(offset == -3*60*60 && found == 1 && error == NULL, NULL); + + // Found, with separators + offset = osync_time_parse_iso_timezone_diff( + "2010-08-10T00:15:00-03:00", &found, &error); + fail_unless(offset == -3*60*60 && found == 1 && error == NULL, NULL); + + // Found, positive offset, full ISO 8601 separaors + offset = osync_time_parse_iso_timezone_diff( + "2010-08-10T00:15:00.000+04:30", &found, &error); + fail_unless(offset == 4*60*60+30*60 && found == 1 && error == NULL, NULL); + + // Error: incomplete offset + offset = osync_time_parse_iso_timezone_diff( + "2010-08-10T00:15:00+04:3", &found, &error); + fail_unless(offset == 0 && found == 0 && error != NULL, NULL); + osync_error_unref(&error); + + // Error: too much offset + offset = osync_time_parse_iso_timezone_diff( + "2010-08-10T00:15:00+04:300", &found, &error); + fail_unless(offset == 0 && found == 0 && error != NULL, NULL); + osync_error_unref(&error); + + // No error, not found: offset without a time (no T found) + offset = osync_time_parse_iso_timezone_diff( + "2010-08-10+04:30", &found, &error); + fail_unless(offset == 0 && found == 0 && error == NULL, NULL); + osync_error_unref(&error); +} +END_TEST + static int test_relative2tm(const char *byday, int month, int year, int expected_day, int expected_wday) { @@ -248,6 +298,7 @@ OSYNC_TESTCASE_START("time") OSYNC_TESTCASE_ADD(time_timezone_diff) +OSYNC_TESTCASE_ADD(time_parse_iso_timezone_diff) OSYNC_TESTCASE_ADD(time_relative2tm) OSYNC_TESTCASE_ADD(time_unix_converters) OSYNC_TESTCASE_ADD(time_utc_offset) |