+/* FIXME: GDateTime was introduced in GLib 2.26, which is not standard on all
+ platforms yet. Therefore, we adapt Andrew Plotkin's implementation for now, and
+ will replace it with the (presumably) more portable GLib facilities later. */
+
+/* Copy a POSIX tm structure to a glkdate. */
+static void
+gli_date_from_tm(glkdate_t *date, struct tm *tm)
+{
+ date->year = 1900 + tm->tm_year;
+ date->month = 1 + tm->tm_mon;
+ date->day = tm->tm_mday;
+ date->weekday = tm->tm_wday;
+ date->hour = tm->tm_hour;
+ date->minute = tm->tm_min;
+ date->second = tm->tm_sec;
+}
+
+/* Copy a glkdate to a POSIX tm structure.
+ This is used in the "glk_date_to_..." functions, which are supposed
+ to normalize the glkdate. We're going to rely on the mktime() /
+ timegm() functions to do that -- except they don't handle microseconds.
+ So we'll have to do that normalization here, adjust the tm_sec value,
+ and return the normalized number of microseconds.
+ */
+static glsi32
+gli_date_to_tm(glkdate_t *date, struct tm *tm)
+{
+ glsi32 microsec;
+
+ bzero(tm, sizeof(tm));
+ tm->tm_year = date->year - 1900;
+ tm->tm_mon = date->month - 1;
+ tm->tm_mday = date->day;
+ tm->tm_wday = date->weekday;
+ tm->tm_hour = date->hour;
+ tm->tm_min = date->minute;
+ tm->tm_sec = date->second;
+ microsec = date->microsec;
+
+ if (microsec >= G_USEC_PER_SEC) {
+ tm->tm_sec += (microsec / G_USEC_PER_SEC);
+ microsec = microsec % G_USEC_PER_SEC;
+ }
+ else if (microsec < 0) {
+ microsec = -1 - microsec;
+ tm->tm_sec -= (1 + microsec / G_USEC_PER_SEC);
+ microsec = (G_USEC_PER_SEC - 1) - (microsec % G_USEC_PER_SEC);
+ }
+
+ return microsec;
+}
+
+/* Convert a GTimeVal, along with a microseconds value, to a glktimeval. */
+static void
+gli_timestamp_to_time(long sec, long microsec, glktimeval_t *time)
+{
+ if (sizeof(sec) <= 4) {
+ /* This platform has 32-bit time, but we can't do anything
+ about that. Hope it's not 2038 yet. */
+ if (sec >= 0)
+ time->high_sec = 0;
+ else
+ time->high_sec = -1;
+ time->low_sec = sec;
+ }
+ else {
+ /* The cast to gint64 shouldn't be necessary, but it
+ suppresses a pointless warning in the 32-bit case.
+ (Remember that we won't be executing this line in the
+ 32-bit case.) */
+ time->high_sec = (((gint64)sec) >> 32) & 0xFFFFFFFF;
+ time->low_sec = sec & 0xFFFFFFFF;
+ }
+
+ time->microsec = microsec;
+}
+
+/* Divide a Unix timestamp by a (positive) value. */
+static glsi32
+gli_simplify_time(long timestamp, glui32 factor)
+{
+ /* We want to round towards negative infinity, which takes a little
+ bit of fussing. */
+ if (timestamp >= 0) {
+ return timestamp / (time_t)factor;
+ }
+ else {
+ return -1 - (((long)-1 - timestamp) / (long)factor);
+ }
+}
+