forked from KolibriOS/kolibrios
452 lines
11 KiB
C
452 lines
11 KiB
C
|
/*
|
||
|
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;
|
||
|
}
|