mactime.c
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:10k
源码类别:

压缩解压

开发平台:

MultiPlatform

  1. /* -----------------------------------------------------------------------------
  2. The original functions (Metrowerks Codewarrior pro 3.0) gmtime, localtime,
  3. mktime and time do not work correctly. The supplied link library mactime.c
  4. contains replacement functions for them.
  5.  *     Caveat: On a Mac, we only know the GMT and DST offsets for
  6.  *     the current time, not for the time in question.
  7.  *     Mac has no support for DST handling.
  8.  *     DST changeover is all manually set by the user.
  9. ------------------------------------------------------------------------------*/
  10. /*****************************************************************************/
  11. /*  Includes                                                                 */
  12. /*****************************************************************************/
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <time.h>
  17. #include <OSUtils.h>
  18. #include "mactime.h"
  19. /*
  20. The MacOS function GetDateTime returns  the
  21. number of seconds elapsed since midnight, January 1, 1904.
  22. */
  23. const unsigned long MacOS_2_Unix = 2082844800L;
  24. /*****************************************************************************/
  25. /*  Macros, typedefs                                                         */
  26. /*****************************************************************************/
  27. #ifndef TEST_TIME_LIB
  28. #define my_gmtime    gmtime
  29. #define my_localtime localtime
  30. #define my_mktime    mktime
  31. #define my_time      time
  32. #endif
  33. /*****************************************************************************/
  34. /*  Prototypes                                                               */
  35. /*****************************************************************************/
  36. /* internal prototypes */
  37. static void clear_tm(struct tm * tm);
  38. static long GMTDelta(void);
  39. static Boolean DaylightSaving(void);
  40. static time_t GetTimeMac(void);
  41. static time_t Mactime(time_t *timer);
  42. static void   normalize(int *i,int *j,int norm);
  43. static struct tm *time2tm(const time_t *timer);
  44. static time_t tm2time(struct tm *tp);
  45. /* Because serial port and SLIP conflict with ReadXPram calls,
  46.    we cache the call here so we don't hang on calling ReadLocation()  */
  47. static void myReadLocation(MachineLocation * loc);
  48. /* prototypes for STD lib replacement functions */
  49. struct tm *my_gmtime(const time_t *t);
  50. struct tm *my_localtime(const time_t *t);
  51. time_t my_mktime(struct tm *tp);
  52. time_t my_time(time_t *t);
  53. /*****************************************************************************/
  54. /*  Functions                                                                */
  55. /*****************************************************************************/
  56.  /*
  57.  *  Mac file times are based on 1904 Jan 1 00:00 local time,
  58.  *  not 1970 Jan 1 00:00 UTC.
  59.  *  So we have to convert the time stamps into UNIX UTC
  60.  *  compatible values.
  61.  */
  62. time_t MacFtime2UnixFtime(unsigned long macftime)
  63. {
  64.     long UTCoffset;
  65.     GetGMToffsetMac(macftime, &UTCoffset);
  66.     MACOS_TO_UNIX(macftime);
  67.     macftime -= UTCoffset;
  68.     return macftime;
  69. }
  70.  /*
  71.  *  Mac file times are based on 1904 Jan 1 00:00 local time,
  72.  *  not 1970 Jan 1 00:00 UTC.
  73.  *  So we have to convert the time stamps into MacOS local
  74.  *  compatible values.
  75.  */
  76. unsigned long UnixFtime2MacFtime(time_t unxftime)
  77. {
  78.     long UTCoffset;
  79.     unsigned long macftime = unxftime;
  80.     UNIX_TO_MACOS(macftime);
  81.     GetGMToffsetMac(macftime, &UTCoffset);
  82.     macftime += UTCoffset;
  83.     return macftime;
  84. }
  85. /*
  86. * This function convert a file-localtime to an another
  87. * file-localtime.
  88. */
  89. time_t AdjustForTZmoveMac(unsigned long macloctim, long s_gmtoffs)
  90. {
  91.     time_t MacGMTTime;
  92.     long UTCoffset;
  93.     /* convert macloctim into corresponding UTC value */
  94.     MacGMTTime = macloctim - s_gmtoffs;
  95.     GetGMToffsetMac(macloctim, &UTCoffset);
  96.     return (MacGMTTime + UTCoffset);
  97. } /* AdjustForTZmove() */
  98. /*
  99.  * This function calculates the difference between the supplied Mac
  100.  * ftime value (local time) and the corresponding UTC time in seconds.
  101.  */
  102. Boolean GetGMToffsetMac(unsigned long mactime, long *UTCoffset)
  103. {
  104. mactime = mactime;
  105. /*
  106.  *     Caveat: On a Mac, we only know the GMT and DST offsets for
  107.  *     the current time, not for the time in question.
  108.  *     Mac has no support for DST handling.
  109.  *     DST changeover is all manually set by the user.
  110.  May be later I can include a support of GMT offset calculation for the
  111.  time in question here.
  112. */
  113.     *UTCoffset = GMTDelta();
  114.     return true;
  115. }
  116. /*****************************************************************************
  117.  *  Standard Library Replacement Functions
  118.  *  gmtime(), mktime(), localtime(), time()
  119.  *
  120.  *  The unix epoch is used here.
  121.  *  These functions gmtime(), mktime(), localtime() and time()
  122.  *  expects and returns unix times.
  123.  *
  124.  * At midnight Jan. 1, 1970 GMT, the local time was
  125.  *    midnight Jan. 1, 1970 + GMTDelta().
  126.  *
  127.  *
  128.  *****************************************************************************/
  129. struct tm *my_gmtime(const time_t *timer)
  130. {
  131.     return time2tm(timer);
  132. }
  133. struct tm *my_localtime(const time_t *timer)
  134. {
  135.     time_t maclocal;
  136.     maclocal = *timer;
  137.     maclocal += GMTDelta();
  138.     return time2tm(&maclocal);
  139. }
  140. time_t my_mktime(struct tm *tp)
  141. {
  142.     time_t maclocal;
  143.     maclocal = tm2time(tp);
  144.     maclocal -= GMTDelta();
  145.     return maclocal;
  146. }
  147. time_t my_time(time_t *time)
  148. {
  149. time_t tmp_time;
  150. GetDateTime(&tmp_time);
  151. MACOS_TO_UNIX(tmp_time);
  152. if (time)
  153.     {
  154.     *time = tmp_time;
  155.     }
  156. return tmp_time;
  157. }
  158. /*****************************************************************************/
  159. /*  static module level functions
  160. /*****************************************************************************/
  161. /*
  162.  * The geographic location and time zone information of a Mac
  163.  * are stored in extended parameter RAM.  The ReadLocation
  164.  * produdure uses the geographic location record, MachineLocation,
  165.  * to read the geographic location and time zone information in
  166.  * extended parameter RAM.
  167.  *
  168.  * Because serial port and SLIP conflict with ReadXPram calls,
  169.  * we cache the call here.
  170.  *
  171.  * Caveat: this caching will give the wrong result if a session
  172.  * extend across the DST changeover time, but
  173.  * this function resets itself every 2 hours.
  174.  */
  175. static void myReadLocation(MachineLocation * loc)
  176. {
  177.     static MachineLocation storedLoc;   /* InsideMac, OSUtilities, page 4-20  */
  178.     static time_t first_call = 0, last_call = 86400;
  179.     if ((last_call - first_call) > 7200)
  180.         {
  181.         GetDateTime(&first_call);
  182.         ReadLocation(&storedLoc);
  183.         }
  184.     GetDateTime(&last_call);
  185.     *loc = storedLoc;
  186. }
  187. static Boolean DaylightSaving(void)
  188. {
  189.     MachineLocation loc;
  190.     unsigned char dlsDelta;
  191.     myReadLocation(&loc);
  192.     dlsDelta =  loc.u.dlsDelta;
  193.     return (dlsDelta != 0);
  194. }
  195. /* current local time = GMTDelta() + GMT
  196.    GMT = local time - GMTDelta()    */
  197. static long GMTDelta(void)
  198. {
  199.     MachineLocation loc;
  200.     long gmtDelta;
  201.     myReadLocation(&loc);
  202.     /*
  203.      * On a Mac, the GMT value is in seconds east of GMT.  For example,
  204.      * San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)
  205.      * east of GMT.  The gmtDelta field is a 3-byte value contained in a
  206.      * long word, so you must take care to get it properly.
  207.      */
  208.     gmtDelta = loc.u.gmtDelta & 0x00FFFFFF;
  209.     if ((gmtDelta & 0x00800000) != 0)
  210.         {
  211.         gmtDelta |= 0xFF000000;
  212.         }
  213.     return gmtDelta;
  214. }
  215. /* This routine simulates stdclib time(), time in seconds since 1.1.1970
  216.    The time is in GMT  */
  217. static time_t GetTimeMac(void)
  218. {
  219.     unsigned long maclocal;
  220.     /*
  221.      * Get the current time expressed as the number of seconds
  222.      * elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).
  223.      * On a Mac, current time accuracy is up to a second.
  224.      */
  225.     GetDateTime(&maclocal);     /* Get Mac local time  */
  226.     maclocal -= GMTDelta();     /* Get Mac GMT  */
  227.     MACOS_TO_UNIX(maclocal);
  228.     return maclocal;            /* return unix GMT  */
  229. }
  230. /*
  231.  *  clear_tm - sets a broken-down time to the equivalent of 1970/1/1 00:00:00
  232.  */
  233. static void clear_tm(struct tm * tm)
  234. {
  235.     tm->tm_sec   =  0;
  236.     tm->tm_min   =  0;
  237.     tm->tm_hour  =  0;
  238.     tm->tm_mday  =  1;
  239.     tm->tm_mon   =  0;
  240.     tm->tm_year  =  0;
  241.     tm->tm_wday  =  1;
  242.     tm->tm_yday  =  0;
  243.     tm->tm_isdst = -1;
  244. }
  245. static void normalize(int *i,int *j,int norm)
  246. {
  247.   while(*i < 0)
  248.     {
  249.     *i += norm;
  250.     (*j)--;
  251.     }
  252.   while(*i >= norm)
  253.     {
  254.     *i -= norm;
  255.     (*j)++;
  256.     }
  257. }
  258. /*  Returns the GMT times  */
  259. static time_t Mactime(time_t *timer)
  260. {
  261.     time_t t = GetTimeMac();
  262.     if (timer != NULL)
  263.         *timer = t;
  264.     return t;
  265. }
  266. static struct tm *time2tm(const time_t *timer)
  267. {
  268.     DateTimeRec dtr;
  269.     MachineLocation loc;
  270.     time_t macLocal = *timer;
  271.     static struct tm statictime;
  272.     static const short monthday[12] =
  273.         {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  274.     /* macLocal -= GMTDelta();  */
  275.     UNIX_TO_MACOS(macLocal);
  276.     SecondsToDate(macLocal, &dtr);
  277.     statictime.tm_sec  = dtr.second;         /* second, from 0 to 59 */
  278.     statictime.tm_min  = dtr.minute;         /* minute, from 0 to 59 */
  279.     statictime.tm_hour = dtr.hour;           /* hour, from 0 to 23 */
  280.     statictime.tm_mday = dtr.day;            /* day of the month, from 1 to 31 */
  281.     statictime.tm_mon  = dtr.month     - 1;  /* month, 1= January and 12 = December */
  282.     statictime.tm_year = dtr.year   - 1900;  /* year, ranging from 1904 to 2040 */
  283.     statictime.tm_wday = dtr.dayOfWeek - 1;  /* day of the week, 1 = Sun, 7 = Sat */
  284.     statictime.tm_yday = monthday[statictime.tm_mon]
  285.                          + statictime.tm_mday - 1;
  286.     if (2 < statictime.tm_mon && !(statictime.tm_year & 3))
  287.         {
  288.         ++statictime.tm_yday;
  289.         }
  290.     myReadLocation(&loc);
  291.     statictime.tm_isdst = DaylightSaving();
  292.     return(&statictime);
  293. }
  294. static time_t tm2time(struct tm *tp)
  295. {
  296. time_t intMacTime;
  297. DateTimeRec  dtr;
  298.  normalize(&tp->tm_sec, &tp->tm_min, 60);
  299.  normalize(&tp->tm_min, &tp->tm_hour,60);
  300.  normalize(&tp->tm_hour,&tp->tm_mday,24);
  301.  normalize(&tp->tm_mon, &tp->tm_year,12);
  302.  dtr.year    = tp->tm_year + 1900;  /* years since 1900 */
  303.  dtr.month   = tp->tm_mon  +    1;  /* month, 0 = January and 11 = December */
  304.  dtr.day     = tp->tm_mday;         /* day of the month, from 1 to 31 */
  305.  dtr.hour    = tp->tm_hour;         /* hour, from 0 to 23 */
  306.  dtr.minute  = tp->tm_min;          /* minute, from 0 to 59 */
  307.  dtr.second  = tp->tm_sec;          /* second, from 0 to 59 */
  308.  DateToSeconds(&dtr, &intMacTime);
  309.  MACOS_TO_UNIX(intMacTime);
  310.  /* intMacTime -= GMTDelta(); */
  311.  return intMacTime;
  312. }