summaryrefslogtreecommitdiff
path: root/macos/source/mactime.c
diff options
context:
space:
mode:
Diffstat (limited to 'macos/source/mactime.c')
-rw-r--r--macos/source/mactime.c451
1 files changed, 451 insertions, 0 deletions
diff --git a/macos/source/mactime.c b/macos/source/mactime.c
new file mode 100644
index 0000000..af9ad5e
--- /dev/null
+++ b/macos/source/mactime.c
@@ -0,0 +1,451 @@
+/*
+ Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
+
+ See the accompanying file LICENSE, version 2000-Apr-09 or later
+ (the contents of which are also included in zip.h) for terms of use.
+ If, for some reason, all these files are missing, the Info-ZIP license
+ also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
+*/
+/* -----------------------------------------------------------------------------
+
+The original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,
+mktime and time do not work correctly. The supplied link library mactime.c
+contains replacement functions for them.
+
+ * Caveat: On a Mac, we only know the GMT and DST offsets for
+ * the current time, not for the time in question.
+ * Mac has no support for DST handling.
+ * DST changeover is all manually set by the user.
+
+
+------------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/* Includes */
+/*****************************************************************************/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <OSUtils.h>
+
+#include "mactime.h"
+
+
+/*
+The MacOS function GetDateTime returns the
+number of seconds elapsed since midnight, January 1, 1904.
+*/
+const unsigned long MacOS_2_Unix = 2082844800L;
+
+
+/*****************************************************************************/
+/* Macros, typedefs */
+/*****************************************************************************/
+
+
+#ifndef TEST_TIME_LIB
+#define my_gmtime gmtime
+#define my_localtime localtime
+#define my_mktime mktime
+#define my_time time
+#endif
+
+
+/*****************************************************************************/
+/* Prototypes */
+/*****************************************************************************/
+/* internal prototypes */
+static void clear_tm(struct tm * tm);
+static long GMTDelta(void);
+static Boolean DaylightSaving(void);
+static time_t GetTimeMac(void);
+static time_t Mactime(time_t *timer);
+static void normalize(int *i,int *j,int norm);
+static struct tm *time2tm(const time_t *timer);
+static time_t tm2time(struct tm *tp);
+
+/* Because serial port and SLIP conflict with ReadXPram calls,
+ we cache the call here so we don't hang on calling ReadLocation() */
+static void myReadLocation(MachineLocation * loc);
+
+
+/* prototypes for STD lib replacement functions */
+struct tm *my_gmtime(const time_t *t);
+struct tm *my_localtime(const time_t *t);
+time_t my_mktime(struct tm *tp);
+time_t my_time(time_t *t);
+
+
+/*****************************************************************************/
+/* Functions */
+/*****************************************************************************/
+
+ /*
+ * Mac file times are based on 1904 Jan 1 00:00 local time,
+ * not 1970 Jan 1 00:00 UTC.
+ * So we have to convert the time stamps into UNIX UTC
+ * compatible values.
+ */
+time_t MacFtime2UnixFtime(unsigned long macftime)
+{
+ long UTCoffset;
+
+ GetGMToffsetMac(macftime, &UTCoffset);
+ MACOS_TO_UNIX(macftime);
+ macftime -= UTCoffset;
+
+ return macftime;
+}
+
+
+ /*
+ * Mac file times are based on 1904 Jan 1 00:00 local time,
+ * not 1970 Jan 1 00:00 UTC.
+ * So we have to convert the time stamps into MacOS local
+ * compatible values.
+ */
+unsigned long UnixFtime2MacFtime(time_t unxftime)
+{
+ long UTCoffset;
+ unsigned long macftime = unxftime;
+
+ UNIX_TO_MACOS(macftime);
+ GetGMToffsetMac(macftime, &UTCoffset);
+ macftime += UTCoffset;
+
+ return macftime;
+}
+
+
+
+
+
+/*
+* This function convert a file-localtime to an another
+* file-localtime.
+*/
+time_t AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs)
+{
+ time_t MacGMTTime;
+ long UTCoffset;
+
+ /* convert macloctim into corresponding UTC value */
+ MacGMTTime = macloctim - s_gmtoffs;
+ GetGMToffsetMac(macloctim, &UTCoffset);
+
+ return (MacGMTTime + UTCoffset);
+} /* AdjustForTZmove() */
+
+
+
+
+/*
+ * This function calculates the difference between the supplied Mac
+ * ftime value (local time) and the corresponding UTC time in seconds.
+ */
+Boolean GetGMToffsetMac(unsigned long mactime, long *UTCoffset)
+{
+
+mactime = mactime;
+/*
+ * Caveat: On a Mac, we only know the GMT and DST offsets for
+ * the current time, not for the time in question.
+ * Mac has no support for DST handling.
+ * DST changeover is all manually set by the user.
+
+ May be later I can include a support of GMT offset calculation for the
+ time in question here.
+*/
+ *UTCoffset = GMTDelta();
+
+ return true;
+}
+
+
+
+
+
+
+
+/*****************************************************************************
+ * Standard Library Replacement Functions
+ * gmtime(), mktime(), localtime(), time()
+ *
+ * The unix epoch is used here.
+ * These functions gmtime(), mktime(), localtime() and time()
+ * expects and returns unix times.
+ *
+ * At midnight Jan. 1, 1970 GMT, the local time was
+ * midnight Jan. 1, 1970 + GMTDelta().
+ *
+ *
+ *****************************************************************************/
+
+
+struct tm *my_gmtime(const time_t *timer)
+{
+ return time2tm(timer);
+}
+
+
+
+
+struct tm *my_localtime(const time_t *timer)
+{
+ time_t maclocal;
+
+ maclocal = *timer;
+ maclocal += GMTDelta();
+
+ return time2tm(&maclocal);
+}
+
+
+
+
+time_t my_mktime(struct tm *tp)
+{
+ time_t maclocal;
+
+ maclocal = tm2time(tp);
+ maclocal -= GMTDelta();
+
+ return maclocal;
+}
+
+
+
+
+
+
+time_t my_time(time_t *time)
+{
+time_t tmp_time;
+
+GetDateTime(&tmp_time);
+
+MACOS_TO_UNIX(tmp_time);
+
+if (time)
+ {
+ *time = tmp_time;
+ }
+
+return tmp_time;
+}
+
+
+
+/*****************************************************************************/
+/* static module level functions
+/*****************************************************************************/
+
+
+/*
+ * The geographic location and time zone information of a Mac
+ * are stored in extended parameter RAM. The ReadLocation
+ * produdure uses the geographic location record, MachineLocation,
+ * to read the geographic location and time zone information in
+ * extended parameter RAM.
+ *
+ * Because serial port and SLIP conflict with ReadXPram calls,
+ * we cache the call here.
+ *
+ * Caveat: this caching will give the wrong result if a session
+ * extend across the DST changeover time, but
+ * this function resets itself every 2 hours.
+ */
+static void myReadLocation(MachineLocation * loc)
+{
+ static MachineLocation storedLoc; /* InsideMac, OSUtilities, page 4-20 */
+ static time_t first_call = 0, last_call = 86400;
+
+ if ((last_call - first_call) > 7200)
+ {
+ GetDateTime(&first_call);
+ ReadLocation(&storedLoc);
+ }
+
+ GetDateTime(&last_call);
+ *loc = storedLoc;
+}
+
+
+
+
+static Boolean DaylightSaving(void)
+{
+ MachineLocation loc;
+ unsigned char dlsDelta;
+
+ myReadLocation(&loc);
+ dlsDelta = loc.u.dlsDelta;
+
+ return (dlsDelta != 0);
+}
+
+
+
+
+/* current local time = GMTDelta() + GMT
+ GMT = local time - GMTDelta() */
+static long GMTDelta(void)
+{
+ MachineLocation loc;
+ long gmtDelta;
+
+ myReadLocation(&loc);
+
+ /*
+ * On a Mac, the GMT value is in seconds east of GMT. For example,
+ * San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)
+ * east of GMT. The gmtDelta field is a 3-byte value contained in a
+ * long word, so you must take care to get it properly.
+ */
+ gmtDelta = loc.u.gmtDelta & 0x00FFFFFF;
+ if ((gmtDelta & 0x00800000) != 0)
+ {
+ gmtDelta |= 0xFF000000;
+ }
+
+ return gmtDelta;
+}
+
+
+
+/* This routine simulates stdclib time(), time in seconds since 1.1.1970
+ The time is in GMT */
+static time_t GetTimeMac(void)
+{
+ unsigned long maclocal;
+
+
+ /*
+ * Get the current time expressed as the number of seconds
+ * elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).
+ * On a Mac, current time accuracy is up to a second.
+ */
+
+ GetDateTime(&maclocal); /* Get Mac local time */
+ maclocal -= GMTDelta(); /* Get Mac GMT */
+ MACOS_TO_UNIX(maclocal);
+
+ return maclocal; /* return unix GMT */
+}
+
+
+
+
+/*
+ * clear_tm - sets a broken-down time to the equivalent of 1970/1/1 00:00:00
+ */
+
+static void clear_tm(struct tm * tm)
+{
+ tm->tm_sec = 0;
+ tm->tm_min = 0;
+ tm->tm_hour = 0;
+ tm->tm_mday = 1;
+ tm->tm_mon = 0;
+ tm->tm_year = 0;
+ tm->tm_wday = 1;
+ tm->tm_yday = 0;
+ tm->tm_isdst = -1;
+}
+
+
+static void normalize(int *i,int *j,int norm)
+{
+ while(*i < 0)
+ {
+ *i += norm;
+ (*j)--;
+ }
+
+ while(*i >= norm)
+ {
+ *i -= norm;
+ (*j)++;
+ }
+}
+
+
+
+/* Returns the GMT times */
+static time_t Mactime(time_t *timer)
+{
+ time_t t = GetTimeMac();
+
+ if (timer != NULL)
+ *timer = t;
+
+ return t;
+}
+
+
+
+
+static struct tm *time2tm(const time_t *timer)
+{
+ DateTimeRec dtr;
+ MachineLocation loc;
+ time_t macLocal = *timer;
+
+ static struct tm statictime;
+ static const short monthday[12] =
+ {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+ UNIX_TO_MACOS(macLocal);
+ SecondsToDate(macLocal, &dtr);
+
+ statictime.tm_sec = dtr.second; /* second, from 0 to 59 */
+ statictime.tm_min = dtr.minute; /* minute, from 0 to 59 */
+ statictime.tm_hour = dtr.hour; /* hour, from 0 to 23 */
+ statictime.tm_mday = dtr.day; /* day of the month, from 1 to 31 */
+ statictime.tm_mon = dtr.month - 1; /* month, 1= January and 12 = December */
+ statictime.tm_year = dtr.year - 1900; /* year, ranging from 1904 to 2040 */
+ statictime.tm_wday = dtr.dayOfWeek - 1; /* day of the week, 1 = Sun, 7 = Sat */
+
+ statictime.tm_yday = monthday[statictime.tm_mon]
+ + statictime.tm_mday - 1;
+
+ if (2 < statictime.tm_mon && !(statictime.tm_year & 3))
+ {
+ ++statictime.tm_yday;
+ }
+
+ myReadLocation(&loc);
+ statictime.tm_isdst = DaylightSaving();
+
+ return(&statictime);
+}
+
+
+
+
+
+static time_t tm2time(struct tm *tp)
+{
+time_t intMacTime;
+DateTimeRec dtr;
+
+ normalize(&tp->tm_sec, &tp->tm_min, 60);
+ normalize(&tp->tm_min, &tp->tm_hour,60);
+ normalize(&tp->tm_hour,&tp->tm_mday,24);
+ normalize(&tp->tm_mon, &tp->tm_year,12);
+
+ dtr.year = tp->tm_year + 1900; /* years since 1900 */
+ dtr.month = tp->tm_mon + 1; /* month, 0 = January and 11 = December */
+ dtr.day = tp->tm_mday; /* day of the month, from 1 to 31 */
+ dtr.hour = tp->tm_hour; /* hour, from 0 to 23 */
+ dtr.minute = tp->tm_min; /* minute, from 0 to 59 */
+ dtr.second = tp->tm_sec; /* second, from 0 to 59 */
+
+ DateToSeconds(&dtr, &intMacTime);
+
+ MACOS_TO_UNIX(intMacTime);
+
+ return intMacTime;
+}