home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / md / mac / mactime.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  8.1 KB  |  267 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include <OSUtils.h>
  20. #include <time.h>
  21.  
  22. #include "primpl.h"
  23.  
  24. PR_IMPLEMENT(UnsignedWide) dstLocalBaseMicroseconds;
  25. PR_IMPLEMENT(unsigned long) gJanuaryFirst1970Seconds;
  26.  
  27. /*
  28.  * The geographic location and time zone information of a Mac
  29.  * are stored in extended parameter RAM.  The ReadLocation
  30.  * produdure uses the geographic location record, MachineLocation,
  31.  * to read the geographic location and time zone information in
  32.  * extended parameter RAM.
  33.  *
  34.  * Because serial port and SLIP conflict with ReadXPram calls,
  35.  * we cache the call here.
  36.  *
  37.  * Caveat: this caching will give the wrong result if a session
  38.  * extend across the DST changeover time.
  39.  */
  40.  
  41. static void MyReadLocation(MachineLocation *loc)
  42. {
  43.     static MachineLocation storedLoc;
  44.     static Boolean didReadLocation = false;
  45.     
  46.     if (!didReadLocation) {
  47.         ReadLocation(&storedLoc);
  48.         didReadLocation = true;
  49.     }
  50.     *loc = storedLoc;
  51. }
  52.  
  53. static long GMTDelta(void)
  54. {
  55.     MachineLocation loc;
  56.     long gmtDelta;
  57.  
  58.     MyReadLocation(&loc);
  59.     gmtDelta = loc.u.gmtDelta & 0x00ffffff;
  60.     if (gmtDelta & 0x00800000) {    /* test sign extend bit */
  61.         gmtDelta |= 0xff000000;
  62.     }
  63.     return gmtDelta;
  64. }
  65.  
  66. void MacintoshInitializeTime(void)
  67. {
  68.     /*
  69.      * The NSPR epoch is midnight, Jan. 1, 1970 GMT.
  70.      *
  71.      * At midnight Jan. 1, 1970 GMT, the local time was
  72.      *     midnight Jan. 1, 1970 + GMTDelta().
  73.      *
  74.      * Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
  75.      *     = 2082844800 seconds since the Mac epoch.
  76.      * (There were 17 leap years from 1904 to 1970.)
  77.      *
  78.      * So the NSPR epoch is 2082844800 + GMTDelta() seconds since
  79.      * the Mac epoch.  Whew! :-)
  80.      */
  81.     gJanuaryFirst1970Seconds = 2082844800 + GMTDelta();
  82.  
  83.     /*
  84.      * Set up dstLocalBaseMicroseconds just for "prmjtime.c" for Mocha
  85.      * needs.  The entire MOcha time needs to be rewritten using NSPR 2.0
  86.      * time.
  87.      */
  88.     {
  89.     UnsignedWide            upTime;
  90.     unsigned long            currentLocalTimeSeconds,
  91.                             startupTimeSeconds;
  92.     uint64                    startupTimeMicroSeconds;
  93.     uint32                    upTimeSeconds;    
  94.     uint64                    oneMillion, upTimeSecondsLong, microSecondsToSeconds;
  95.  
  96.     Microseconds(&upTime);
  97.     
  98.     GetDateTime(¤tLocalTimeSeconds);
  99.     
  100.     LL_I2L(microSecondsToSeconds, PR_USEC_PER_SEC);
  101.     LL_DIV(upTimeSecondsLong,  *((uint64 *)&upTime), microSecondsToSeconds);
  102.     LL_L2I(upTimeSeconds, upTimeSecondsLong);
  103.     
  104.     startupTimeSeconds = currentLocalTimeSeconds - upTimeSeconds;
  105.     
  106.     startupTimeSeconds -= gJanuaryFirst1970Seconds;
  107.     
  108.     //    Now convert the startup time into a wide so that we
  109.     //    can figure out GMT and DST.
  110.     
  111.     LL_I2L(startupTimeMicroSeconds, startupTimeSeconds);
  112.     LL_I2L(oneMillion, PR_USEC_PER_SEC);
  113.     LL_MUL(dstLocalBaseMicroseconds, oneMillion, startupTimeMicroSeconds);
  114.     }
  115. }
  116.  
  117. /*
  118.  *-----------------------------------------------------------------------
  119.  *
  120.  * PR_Now --
  121.  *
  122.  *     Returns the current time in microseconds since the epoch.
  123.  *     The epoch is midnight January 1, 1970 GMT.
  124.  *     The implementation is machine dependent.  This is the Mac
  125.  *     Implementation.
  126.  *     Cf. time_t time(time_t *tp)
  127.  *
  128.  *-----------------------------------------------------------------------
  129.  */
  130.  
  131. PRTime PR_Now(void)
  132. {
  133.     unsigned long currentTime;    /* unsigned 32-bit integer, ranging
  134.                                      from midnight Jan. 1, 1904 to 
  135.                                      6:28:15 AM Feb. 6, 2040 */
  136.     PRTime retVal;
  137.     int64  usecPerSec;
  138.  
  139.     /*
  140.      * Get the current time expressed as the number of seconds
  141.      * elapsed since the Mac epoch, midnight, Jan. 1, 1904 (local time).
  142.      * On a Mac, current time accuracy is up to a second.
  143.      */
  144.     GetDateTime(¤tTime);
  145.  
  146.     /*
  147.      * Express the current time relative to the NSPR epoch,
  148.      * midnight, Jan. 1, 1970 GMT.
  149.      *
  150.      * At midnight Jan. 1, 1970 GMT, the local time was
  151.      *     midnight Jan. 1, 1970 + GMTDelta().
  152.      *
  153.      * Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
  154.      *     = 2082844800 seconds since the Mac epoch.
  155.      * (There were 17 leap years from 1904 to 1970.)
  156.      *
  157.      * So the NSPR epoch is 2082844800 + GMTDelta() seconds since
  158.      * the Mac epoch.  Whew! :-)
  159.      */
  160.     currentTime = currentTime - 2082844800 - GMTDelta();
  161.  
  162.     /* Convert seconds to microseconds */
  163.     LL_I2L(usecPerSec, PR_USEC_PER_SEC);
  164.     LL_I2L(retVal, currentTime);
  165.     LL_MUL(retVal, retVal, usecPerSec);
  166.  
  167.     return retVal;
  168. }
  169.  
  170. /*
  171.  *-------------------------------------------------------------------------
  172.  *
  173.  * PR_LocalTimeParameters --
  174.  * 
  175.  *     returns the time parameters for the local time zone
  176.  *
  177.  *     This is the machine-dependent implementation for Mac.
  178.  *
  179.  *     Caveat: On a Mac, we only know the GMT and DST offsets for
  180.  *     the current time, not for the time in question.
  181.  *     Mac has no support for DST handling.
  182.  *     DST changeover is all manually set by the user.
  183.  *
  184.  *-------------------------------------------------------------------------
  185.  */
  186.  
  187. PRTimeParameters PR_LocalTimeParameters(const PRExplodedTime *gmt)
  188. {
  189. #pragma unused (gmt)
  190.  
  191.     PRTimeParameters retVal;
  192.     MachineLocation loc;
  193.  
  194.     MyReadLocation(&loc);
  195.  
  196.     /* 
  197.      * On a Mac, the GMT value is in seconds east of GMT.  For example,
  198.      * San Francisco is at -28,800 seconds (8 hours * 3600 seconds per hour)
  199.      * east of GMT.  The gmtDelta field is a 3-byte value contained in a
  200.      * long word, so you must take care to get it properly.
  201.      */
  202.  
  203.     retVal.tp_gmt_offset = loc.u.gmtDelta & 0x00ffffff;
  204.     if (retVal.tp_gmt_offset & 0x00800000) {    /* test sign extend bit */
  205.     retVal.tp_gmt_offset |= 0xff000000;
  206.     }
  207.  
  208.     /*
  209.      * The daylight saving time value, dlsDelta, is a signed byte
  210.      * value representing the offset for the hour field -- whether
  211.      * to add 1 hour, subtract 1 hour, or make no change at all.
  212.      */
  213.  
  214.     if (loc.u.dlsDelta) {
  215.         retVal.tp_gmt_offset -= 3600;
  216.         retVal.tp_dst_offset = 3600;
  217.     } else {
  218.         retVal.tp_dst_offset = 0;
  219.     }
  220.     return retVal;
  221. }
  222.  
  223. PRIntervalTime _MD_GetInterval(void)
  224. {
  225.     PRIntervalTime retVal;
  226.     PRUint64 upTime, micrototimer;    
  227.  
  228.     /*
  229.      * Use the Microseconds procedure to obtain the number of
  230.      * microseconds elapsed since system startup time.
  231.      */
  232.     Microseconds((UnsignedWide *)&upTime);
  233.     LL_I2L(micrototimer, (kMacTimerInMiliSecs * PR_MSEC_PER_SEC));
  234.     LL_DIV(upTime, upTime, micrototimer);
  235.     LL_L2I(retVal, upTime);
  236.     
  237.     return retVal;
  238. }
  239.  
  240. struct tm *Maclocaltime(const time_t * t)
  241. {
  242.     DateTimeRec dtr;
  243.     MachineLocation loc;
  244.     time_t macLocal = *t + gJanuaryFirst1970Seconds; /* GMT Mac */
  245.     static struct tm statictime;
  246.     static const short monthday[12] =
  247.         {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  248.  
  249.     SecondsToDate(macLocal, &dtr);
  250.     statictime.tm_sec = dtr.second;
  251.     statictime.tm_min = dtr.minute;
  252.     statictime.tm_hour = dtr.hour;
  253.     statictime.tm_mday = dtr.day;
  254.     statictime.tm_mon = dtr.month - 1;
  255.     statictime.tm_year = dtr.year - 1900;
  256.     statictime.tm_wday = dtr.dayOfWeek - 1;
  257.     statictime.tm_yday = monthday[statictime.tm_mon]
  258.         + statictime.tm_mday - 1;
  259.     if (2 < statictime.tm_mon && !(statictime.tm_year & 3))
  260.         ++statictime.tm_yday;
  261.     MyReadLocation(&loc);
  262.     statictime.tm_isdst = loc.u.dlsDelta;
  263.     return(&statictime);
  264. }
  265.  
  266.  
  267.