diff options
-rw-r--r-- | e-util/ChangeLog | 5 | ||||
-rw-r--r-- | e-util/Makefile.am | 2 | ||||
-rw-r--r-- | e-util/e-time-utils.c | 292 | ||||
-rw-r--r-- | e-util/e-time-utils.h | 35 |
4 files changed, 334 insertions, 0 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 8cf1b9c216..cff7183efa 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,8 @@ +2001-03-04 Damon Chaplin <damon@ximian.com> + + * e-time-utils.[hc]: new files to contain functions to parse and + format dates and times for various calendar widgets. + 2001-03-01 Dan Winship <danw@ximian.com> * e-path.c (e_path_to_physical): New function to turn foo/bar into diff --git a/e-util/Makefile.am b/e-util/Makefile.am index fd9364ccd4..8a89dbe447 100644 --- a/e-util/Makefile.am +++ b/e-util/Makefile.am @@ -39,6 +39,8 @@ libeutil_la_SOURCES = \ e-path.h \ e-sexp.c \ e-sexp.h \ + e-time-utils.c \ + e-time-utils.h \ e-dbhash.c \ e-dbhash.h \ md5-utils.c \ diff --git a/e-util/e-time-utils.c b/e-util/e-time-utils.c new file mode 100644 index 0000000000..80eb38e2e9 --- /dev/null +++ b/e-util/e-time-utils.c @@ -0,0 +1,292 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Time utility functions + * + * Author: + * Damon Chaplin (damon@ximian.com) + * + * (C) 2001 Ximian, Inc. + */ + +#include <config.h> + +/* We need this for strptime. */ +#define _XOPEN_SOURCE 500 +#define __USE_XOPEN +#include <time.h> +#include <sys/time.h> +#undef _XOPEN_SOURCE +#undef __USE_XOPEN + +#include <ctype.h> +#include <glib.h> +#include <libgnome/gnome-defs.h> +#include <libgnome/gnome-i18n.h> +#include "e-time-utils.h" + +static gboolean string_is_empty (const char *value); + + +/* + * Parses a string containing a date and a time. The date is expected to be + * in a format something like "Wed 3/13/00 14:20:00", though we use gettext + * to support the appropriate local formats and we try to accept slightly + * different formats, e.g. the weekday can be skipped and we can accept 12-hour + * formats with an am/pm string. + * + * Returns E_TIME_PARSE_OK if it could not be parsed, E_TIME_PARSE_NONE if it + * was empty, or E_TIME_PARSE_INVALID if it couldn't be parsed. + */ +ETimeParseStatus +e_time_parse_date_and_time (const char *value, + struct tm *result) +{ + struct tm discard_tm, time_tm; + struct tm *today_tm; + time_t t; + const char *pos, *parse_end; + char *format[4]; + gboolean parsed_date = FALSE, parsed_time = FALSE; + gint i; + + if (string_is_empty (value)) + return E_TIME_PARSE_NONE; + + pos = value; + + /* Skip any whitespace. */ + while (isspace (*pos)) + pos++; + + /* Skip any weekday name, full or abbreviated. */ + parse_end = strptime (pos, "%a ", &discard_tm); + if (parse_end) + pos = parse_end; + + memset (result, 0, sizeof (*result)); + /* strptime format for a date. */ + parse_end = strptime (pos, _("%m/%d/%Y"), result); + if (parse_end) { + pos = parse_end; + parsed_date = TRUE; + } + + /* Skip any whitespace. */ + while (isspace (*pos)) + pos++; + + /* Skip any weekday name, full or abbreviated, again. */ + parse_end = strptime (pos, "%a ", &discard_tm); + if (parse_end) + pos = parse_end; + + + /* strptime format for a time of day, in 12-hour format. + If it is not appropriate in the locale set to an empty string. */ + format[0] = _("%I:%M:%S %p%n"); + + /* strptime format for a time of day, in 24-hour format. */ + format[1] = _("%H:%M:%S%n"); + + /* strptime format for time of day, without seconds, 12-hour format. + If it is is not appropriate in the locale set to an empty string. */ + format[2] = _("%I:%M %p%n"); + + /* strptime format for time of day, without seconds 24-hour format. */ + format[3] = _("%H:%M%n"); + + for (i = 0; i < sizeof (format) / sizeof (format[0]); i++) { + memset (&time_tm, 0, sizeof (time_tm)); + parse_end = strptime (pos, format[i], &time_tm); + if (parse_end) { + pos = parse_end; + parsed_time = TRUE; + break; + } + } + + /* Skip any whitespace. */ + while (isspace (*pos)) + pos++; + + /* If we haven't already parsed a date, try again. */ + if (!parsed_date) { + memset (result, 0, sizeof (*result)); + /* strptime format for a date. */ + parse_end = strptime (pos, _("%m/%d/%Y"), result); + if (parse_end) { + pos = parse_end; + parsed_date = TRUE; + } + } + + /* If we don't have a date or a time it must be invalid. */ + if (!parsed_date && !parsed_time) + return E_TIME_PARSE_INVALID; + + if (parsed_date) { + /* If a 2-digit year was used we use the current century. */ + if (result->tm_year < 0) { + t = time (NULL); + today_tm = localtime (&t); + + /* This should convert it into a value from 0 to 99. */ + result->tm_year += 1900; + + /* Now add on the century. */ + result->tm_year += today_tm->tm_year + - (today_tm->tm_year % 100); + } + } else { + /* If we didn't get a date we use the current day. */ + t = time (NULL); + today_tm = localtime (&t); + result->tm_mday = today_tm->tm_mday; + result->tm_mon = today_tm->tm_mon; + result->tm_year = today_tm->tm_year; + } + + if (parsed_time) { + result->tm_hour = time_tm.tm_hour; + result->tm_min = time_tm.tm_min; + result->tm_sec = time_tm.tm_sec; + } else { + result->tm_hour = 0; + result->tm_min = 0; + result->tm_sec = 0; + } + + result->tm_isdst = -1; + + return E_TIME_PARSE_OK; +} + + +/* + * Parses a string containing a time. It is expected to be in a format + * something like "14:20:00", though we use gettext to support the appropriate + * local formats and we try to accept slightly different formats, e.g. we can + * accept 12-hour formats with an am/pm string. + * + * Returns E_TIME_PARSE_OK if it could not be parsed, E_TIME_PARSE_NONE if it + * was empty, or E_TIME_PARSE_INVALID if it couldn't be parsed. + */ +ETimeParseStatus +e_time_parse_time (const char *value, + struct tm *result) +{ + const char *pos, *parse_end; + char *format[4]; + gboolean parsed_time = FALSE; + gint i; + + if (string_is_empty (value)) { + memset (result, 0, sizeof (*result)); + result->tm_isdst = -1; + return E_TIME_PARSE_NONE; + } + + pos = value; + + /* Skip any whitespace. */ + while (isspace (*pos)) + pos++; + + /* strptime format for a time of day, in 12-hour format. + If it is not appropriate in the locale set to an empty string. */ + format[0] = _("%I:%M:%S %p%n"); + + /* strptime format for a time of day, in 24-hour format. */ + format[1] = _("%H:%M:%S%n"); + + /* strptime format for time of day, without seconds, 12-hour format. + If it is is not appropriate in the locale set to an empty string. */ + format[2] = _("%I:%M %p%n"); + + /* strptime format for time of day, without seconds 24-hour format. */ + format[3] = _("%H:%M%n"); + + for (i = 0; i < sizeof (format) / sizeof (format[0]); i++) { + memset (result, 0, sizeof (*result)); + parse_end = strptime (pos, format[i], result); + if (parse_end) { + pos = parse_end; + parsed_time = TRUE; + break; + } + } + + result->tm_isdst = -1; + + /* If we don't have a date or a time it must be invalid. */ + if (!parsed_time) + return E_TIME_PARSE_INVALID; + + return E_TIME_PARSE_OK; +} + + +/* Returns whether a string is NULL, empty, or full of whitespace */ +static gboolean +string_is_empty (const char *value) +{ + const char *p; + gboolean empty = TRUE; + + if (value) { + p = value; + while (*p) { + if (!isspace (*p)) { + empty = FALSE; + break; + } + p++; + } + } + return empty; +} + + +/* Creates a string representation of a time value and stores it in result. + result_size is the size of the result buffer, and should be about 64 to + be safe. If show_midnight is FALSE, and the time is midnight, then we just + show the date. */ +void +e_time_format_date_and_time (struct tm *date_tm, + gboolean use_24_hour_format, + gboolean show_midnight, + gboolean show_zero_seconds, + char *result, + int result_size) +{ + char *format; + + if (!show_midnight && date_tm->tm_hour == 0 + && date_tm->tm_min == 0 && date_tm->tm_sec == 0) { + /* strftime format of a weekday and a date. */ + format = _("%a %m/%d/%Y"); + } else if (use_24_hour_format) { + if (!show_zero_seconds && date_tm->tm_sec == 0) + /* strftime format of a weekday, a date and a + time, in 24-hour format, without seconds. */ + format = _("%a %m/%d/%Y %H:%M"); + else + /* strftime format of a weekday, a date and a + time, in 24-hour format. */ + format = _("%a %m/%d/%Y %H:%M:%S"); + } else { + if (!show_zero_seconds && date_tm->tm_sec == 0) + /* strftime format of a weekday, a date and a + time, in 12-hour format, without seconds. */ + format = _("%a %m/%d/%Y %I:%M %p"); + else + /* strftime format of a weekday, a date and a + time, in 12-hour format. */ + format = _("%a %m/%d/%Y %I:%M:%S %p"); + } + + /* strftime returns 0 if the string doesn't fit, and leaves the buffer + undefined, so we set it to the empty string in that case. */ + if (strftime (result, result_size, format, date_tm) == 0) + result[0] = '\0'; +} diff --git a/e-util/e-time-utils.h b/e-util/e-time-utils.h new file mode 100644 index 0000000000..f6449a2f61 --- /dev/null +++ b/e-util/e-time-utils.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Time utility functions + * + * Author: + * Damon Chaplin (damon@ximian.com) + * + * (C) 2001 Ximian, Inc. + */ + +#ifndef E_TIME_UTILS +#define E_TIME_UTILS + +typedef enum { + E_TIME_PARSE_OK, + E_TIME_PARSE_NONE, + E_TIME_PARSE_INVALID +} ETimeParseStatus; + +/* Tries to parse a string containing a date and time. */ +ETimeParseStatus e_time_parse_date_and_time (const char *value, + struct tm *result); + +/* Tries to parse a string containing a time. */ +ETimeParseStatus e_time_parse_time (const char *value, + struct tm *result); + +/* Turns a struct tm into a string like "Wed 3/12/00 12:00:00 AM". */ +void e_time_format_date_and_time (struct tm *date_tm, + gboolean use_24_hour_format, + gboolean show_midnight, + gboolean show_zero_seconds, + char *result, + int result_size); +#endif /* E_TIME_UTILS */ |