aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--e-util/ChangeLog5
-rw-r--r--e-util/Makefile.am2
-rw-r--r--e-util/e-time-utils.c292
-rw-r--r--e-util/e-time-utils.h35
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 */