Date/Time Functions

DateTime provides nearly everything you need to manipulate Date and Time from within a C or C++ program.

The Julian Date is used as a single double precision number that precisely represents both the date and time accurately to millisecond precision. This makes it an ideal timestamp for reconstructing events in Sequence of Events processing.

The Gregorian Day, an integer value, is used in the calculation of the Julian Date since it is quick and easy to calculate. The Julian Date is the Gregorian Day plus the fraction of the day plus 1721424.5.

DateTime.h

/*********************************************************************************************
* Copyright (c) 1990 - 2010 David Cass Tyler, PO Box 1026, Willard, NM 87063, (505) 384-5342 *
*********************************************************************************************/

/*
 * DateTime.h - Header File for the Date/Time Functions
 */

#if !defined(DATETIME_H__4915DDA3_D454_4C36_AD25_4F2DF5E21C9B__INCLUDED_)
#define DATETIME_H__4915DDA3_D454_4C36_AD25_4F2DF5E21C9B__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif /* _MSC_VER > 1000 */

#ifndef _INC_STDIO
#include <STDIO.H>
#endif   /* _INC_STDIO */

#ifndef _INC_TIME
#include <TIME.H>
#endif   /* _INC_TIME */

#ifndef _WINBASE_

#ifndef FALSE
#define FALSE  0
#endif

#ifndef TRUE
#define TRUE   1
#endif

typedef int BOOL;

typedef unsigned short WORD;

typedef struct _SYSTEMTIME {

   WORD  wYear;
   WORD  wMonth;
   WORD  wDayOfWeek;
   WORD  wDay;
   WORD  wHour;
   WORD  wMinute;
   WORD  wSecond;
   WORD  wMilliseconds;

} SYSTEMTIME, * PSYSTEMTIME, * LPSYSTEMTIME;

typedef short           SQLSMALLINT;
typedef unsigned short  SQLUSMALLINT;
typedef unsigned long   SQLUINTEGER;

typedef struct tagTIMESTAMP_STRUCT {

   SQLSMALLINT    year;
   SQLUSMALLINT   month;
   SQLUSMALLINT   day;
   SQLUSMALLINT   hour;
   SQLUSMALLINT   minute;
   SQLUSMALLINT   second;
   SQLUINTEGER    fraction;

} TIMESTAMP_STRUCT;

#ifndef _WIN32_WINNT
extern __declspec ( dllimport ) void __stdcall GetSystemTime ( LPSYSTEMTIME lpSystemTime );
#else
extern void GetSystemTime ( LPSYSTEMTIME lpSystemTime );
#endif   /* _WIN32_WINNT */

#endif   /* _WINBASE_ */

#ifdef  __cplusplus
extern "C" {
#endif

long int          MDY2GD            ( int nMonth, int nDay, int nYear );
void              GD2MDY            ( long int lnDate, int * pnMonth, int * pnDay, int * pnYear );

double            CAL2JD            ( int nMo, int nDy, int nYear, int nHr, int nMn, int nSc, int nMs );
void              JD2CAL            ( double jdDateTime, int * lpnMo, int * lpnDy, int * lpnYear, int * lpnHr, int * lpnMn, int * lpnSc, int * lpnMs );

void              GetTzInfo         ( int * pnTimeZoneOffsetInHours, int * pfUseDaylightSavingsTime );

BOOL              Year2DST          ( int nYear, int nTimeZoneOffsetInHours, double * putcBeg, double * putcEnd );

double            UTC2Civil         ( double utcDateTime, BOOL * pfDaylightSavingsInEffect,  int nTimeZoneOffsetInHours, BOOL fUseDaylightSavingsTime );
double            Civil2UTC         ( double civDateTime, BOOL * pfDaylightSavingsAmbiguity, int nTimeZoneOffsetInHours, BOOL fUseDaylightSavingsTime );

double            CurrentTime       ( void );

TIMESTAMP_STRUCT  GetCivilTimeStamp ( double utcDateTime );

void              DumpJD2UTC        ( FILE * hFile, char * szLegend, double dblTimeUTC );
void              DumpJD2Civ        ( FILE * hFile, char * szLegend, double dblTimeUTC );

char *            myctime           ( const time_t * plnTime );

#ifdef   __cplusplus
}
#endif

#endif   /* !defined(DATETIME_H__4915DDA3_D454_4C36_AD25_4F2DF5E21C9B__INCLUDED_) */

DateTime.c

/*********************************************************************************************
* Copyright (c) 1990 - 2010 David Cass Tyler, PO Box 1026, Willard, NM 87063, (505) 384-5342 *
*********************************************************************************************/

#include <TIME.H>

#include "DateTime.h"

static BOOL g_fTzSet = FALSE;

/*********************************************************************************************************************
*                                                                                                                    *
*  MDY2GD and GD2MDY Derived from Algorithm 199 of the Collected Algorithms of the ACM                               *
*  see http://portal.acm.org/citation.cfm?doid=366707.390020                                                         *
*                                                                                                                    *
*  The functions MDY2GD() and GD2MDY() convert integer Gregorian Day Number back and forth between calendar dates.   *
*  The Gregorian Calendar was established in 1582 by Pope Gregory XIII and is the calendar that we currently use.    *
*  The Gregorian Day Number, modulo 7, returns a day of the week index where Sunday = 0.                             *
*                                                                                                                    *
*  The functions CAL2JD() and CALUTC() convert double precision floating point astronomical Julian Day number        *
*  back and forth between calendar dates.  Because of its astronomical origins, the Julian Day number changes        *
*  at noon so that it remains the same during a night of observations.                                               *
*                                                                                                                    *
*  "A full discussion of 'Julian Date' is likewise beyond the scope of this manual. It is                            *
*  interesting to note, however, that 'Julian Date' 0,0 was Greenwich Mean Time at noon                              *
*  on January 1, 4713 BC. It is a time scale widely used by astronomers because it is                                *
*  unambiguous, employs no leap-years, and because a single number represents both date                              *
*  and time. For convenience, Gemini's display of 'Julian Date' also includes the day of the                         *
*  week for the longitude of Greenwich, England."                                                                    *
*                                                                                                                    *
*  http://www.losmandy.com/losmandygoto/gemini_manual.pdf                                                            *
*                                                                                                                    *
*  Convert from Month/Day/Year to the Gregorian Day Index                                                            *
*                                                                                                                    *
*  month = 1 to 12                                                                                                   *
*  day   = ? to ?                                                                                                    *
*  year  = 1 to < 32768                                                                                              *
*                                                                                                                    *
*********************************************************************************************************************/

long int MDY2GD ( int nMonth, int nDay, int nYear )

   {  /*                                     Jan   Feb   Mar   Apr   May   Jun   Jly   Aug   Sep   Oct   Nov   Dec   */
   static const int  nDays [ 13 ] = {    0,    0,  -31,  306,  275,  245,  214,  184,  153,  122,   92,   61,   31 };
   static const int  nBias [ 13 ] = {    0,    1,    1,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0 };

   long  nYears, nDate;

   nYears = nYear - nBias [ nMonth ];

   nDate = ( ( nYears / 100 ) * 146097l ) / 4
         + ( ( nYears % 100 ) *    1461 ) / 4
         - nDays [ nMonth ]
         + nDay;

   return nDate;

   }  /* long MDY2GD ( int nMonth, int nDay, int nYear ) */

/* Convert from Gregorian Day Index to Month/Day/Year */

void GD2MDY ( long int lnDate, int * pnMonth, int * pnDay, int * pnYear )

   {     /*                            Jan   Feb   Mar   Apr   May   Jun   Jly   Aug   Sep   Oct   Nov   Dec   */
   static const int  nBias [ 12 ] = {    2,    2,    2,    2,    2,    2,    2,    2,    2,    2,  -10,  -10 };
   long              lnLD, lnYr, lnMo, lnDy;

   lnLD = 4 * ( lnDate + 306 ) - 1;

   lnYr = ( lnLD / 146097l ) * 100;
   lnDy = ( lnLD % 146097l ) /   4;

   lnLD = 4 * lnDy + 3;

   lnYr = ( lnLD / 1461 )     + lnYr;
   lnDy = ( lnLD % 1461 ) / 4 + 1;

   lnLD = 5 * lnDy - 3;

   lnMo = ( lnLD / 153 )     + 1;
   lnDy = ( lnLD % 153 ) / 5 + 1;

   * pnMonth   = ( int ) ( lnMo + nBias [ lnMo - 1 ] );
   * pnDay     = ( int ) ( lnDy );
   * pnYear    = ( int ) ( lnYr + lnMo/11 );

   }  /* void GD2MDY ( long lnDate, int * pnMonth, int * pnDay, int * pnYear ) */

/* Convert From Mo/Dy/Year hh:mm:ss.ms to the Julian Day Number */

double CAL2JD ( int nMo, int nDy, int nYear, int nHr, int nMn, int nSc, int nMs )

   {

   return   ( ( double ) MDY2GD ( nMo, nDy, nYear )   /* Gregorian Day Index        */

            + ( double ) nHr /       24.0             /* Hours Fraction             */
            + ( double ) nMn /     1440.0             /* Minutes Fraction           */
            + ( double ) nSc /    86400.0             /* Seconds Fraction           */
            + ( double ) nMs / 86400000.0             /* Milliseconds Fraction      */

            + 1721424.5 );                            /* Julian Day Number Offset   */

   }  /* double CAL2JD ( int nMo, int nDy, int nYear, int nHr, int nMn, int nSc, int nMs ) */

/* Convert From Julian Day Number To Mo/Dy/Year hh:mm:ss.ms */

void JD2CAL ( double jdDateTime, int * lpnMo, int * lpnDy, int * lpnYear, int * lpnHr, int * lpnMn, int * lpnSc, int * lpnMs )

   {
   long     lnTime;
   double   gdDate;

   /* Convert the Julian Day Number to the Gregorian Day Number                           */

   gdDate = jdDateTime - 1721424.5;                   /* Julian Day Number Offset         */

   /* Convert the Gregorian Day to the Gregorian Calendar Month, Day and lpnYear          */

   GD2MDY ( ( long ) gdDate, lpnMo, lpnDy, lpnYear ); /* Gregorian Day Index              */

   /* Extract the Gregorian Day Fraction ( 0.0 <= fraction < 1.0 ) and convert            */
   /* it into Milliseconds per Day:                                                       */

   /* Milliseconds per Day = Milliseconds per Second                                      */
   /*                      * Seconds      per Minute                                      */
   /*                      * Minutes      per Hour                                        */
   /*                      * Hours        per Day                                         */

   /* 1000 * 60 * 60 * 24 = 86400000                                                      */

   /* ( 0 <= lnTime < 86400000 )                                                          */

   lnTime = ( long ) ( ( gdDate - ( double ) ( ( long ) gdDate ) ) * 86400000.0 + 0.5 );

   /* Convert the Milliseconds to Hours, Minutes, Seconds and Milliseconds:               */
   /*                                                                                     */
   /* Unit = mod ( Milliseconds / Milliseconds per Unit, Units )                          */

   if ( lpnHr ) * lpnHr = ( int ) ( ( lnTime /  3600000L ) %   24L );   /* Hours          */
   if ( lpnMn ) * lpnMn = ( int ) ( ( lnTime /    60000L ) %   60L );   /* Minutes        */
   if ( lpnSc ) * lpnSc = ( int ) ( ( lnTime /     1000L ) %   60L );   /* Seconds        */

   if ( lpnMs ) * lpnMs = ( int ) ( ( lnTime /        1L ) % 1000L );   /* Milliseconds   */

   }  /* void JD2CAL ( double jdDateTime, int * lpnMo, int * lpnDy, int * lpnYear, int * lpnHr, int * lpnMn, int * lpnSc, int * lpnMs ) */

void GetTzInfo ( int * pnTimeZoneOffsetInHours, int * pfUseDaylightSavingsTime )

   {

   _tzset();

   * pnTimeZoneOffsetInHours  = -( _timezone / 3600L );
   * pfUseDaylightSavingsTime = _daylight;

   }  /* void GetTzInfo ( int * pnTimeZoneOffsetInHours, int * pfUseDaylightSavingsTime ) */

/* Compute the Starting and Ending Daylight Savings Times, for this Timezone, Adjusted to UTC Julian Day Numbers (NOT Civil) */

BOOL Year2DST ( int nYear, int nTimeZoneOffsetInHours, double * putcBeg, double * putcEnd )

   {
   int      nMo = 0, nDy = 0;
   double   dblTimeZoneOffset = nTimeZoneOffsetInHours / 24.0;

   /***************************************************************************************************
   *  "Starting in 2007, daylight time begins in the United States on the second Sunday in March      *
   *  and ends on the first Sunday in November. On the second Sunday in March, clocks are set ahead   *
   *  one hour at 2:00 a.m. local standard time, which becomes 3:00 a.m. local daylight time. On      *
   *  the first Sunday in November, clocks are set back one hour at 2:00 a.m. local daylight time,    *
   *  which becomes 1:00 a.m. local standard time. These dates were established by the                *
   *  Energy Policy Act of 2005, Pub. L. no. 109-58, 119 Stat 594 (2005)."                            *
   *                                                                                                  *
   *  see http://aa.usno.navy.mil/faq/docs/daylight_time.php                                          *
   *                                                                                                  *
   *  Compute the First Day of Daylight Savings Time for the Specified Year                           *
   *                                                                                                  *
   *  Note: Remember that the gd() of the last day of the prior month is the                          *
   *        same as the gd() of day zero of the current month.  The expression                        *
   *        Lo = gd ( 5, 0, nYear ), or day zero of May, returns the Gregorian                        *
   *        Day Index of April 30 of the specified year.  By taking advantage                         *
   *        of the fact that the Gregorian Day Index, modulo 7, returns a value                       *
   *        of 0 - 6 where 0 = Sunday, the expression "Lo = gd(5,0,nYear)/7*7;"                       *
   *        effectively truncates the date to the last sunday of the prior                            *
   *        month (April).                                                                            *
   *                                                                                                  *
   *        The expression "Lo = gd(4,0,nYear)/7*7 + 7;" takes advantage of the                       *
   *        fact that the second Sunday of the current month occurs 14 days after                     *
   *        the last Sunday of the prior month and the first Sunday of the current                    *
   *        month occurs 7 days after the last Sunday of the prior month.                             *
   *                                                                                                  *
   *        It starts at 2:00 a.m. (3:00 a.m. DST)                                                    *
   *        It ends   at 1:00 a.m. (2:00 a.m. DST)                                                    *
   *                                                                                                  *
   *  Only Handle Years After 2007                                                                    *
   *                                                                                                  *
   ***************************************************************************************************/

   if ( nYear < 2007 )
      return FALSE;

   /* Compute the First Day of Daylight Savings Time for the Specified Year   */

   GD2MDY ( MDY2GD ( 3, 0, nYear ) / 7 * 7 + 14, &nMo, &nDy, &nYear );
   * putcBeg = CAL2JD ( nMo, nDy, nYear, 2, 0, 0, 0 ) - dblTimeZoneOffset;

   /* Compute the Last Day of Daylight Savings Time for the Specified Year    */

   GD2MDY ( MDY2GD ( 11, 0, nYear ) / 7 * 7 + 7, &nMo, &nDy, &nYear );
   * putcEnd = CAL2JD ( nMo, nDy, nYear, 1, 0, 0, 0 ) - dblTimeZoneOffset;

   /* Return Success!   */

   return TRUE;

   }  /* BOOL Year2DST ( int nYear, int nTimeZoneOffsetInHours, double * putcBeg, double * putcEnd ) */

/* Convert from a UTC Date/Time Index to a Civil Date/Time Index and Tell Me if Daylight Savings Time is In Effect */

double UTC2Civil ( double utcDateTime, BOOL * pfDaylightSavingsInEffect, int nTimeZoneOffsetInHours, BOOL fUseDaylightSavingsTime )

   {
   double   civDateTime    = 0.0;

   double   utcBegDST      = 0.0;
   double   utcEndDST      = 0.0;

   int      nMonth         = 0;
   int      nDay           = 0;
   int      nYear          = 0;

   int      nHour          = 0;
   int      nMinute        = 0;
   int      nSecond        = 0;

   int      nMillisecond   = 0;

   /* Default to NOT Using Daylight Savings Time               */

   if ( pfDaylightSavingsInEffect )
      * pfDaylightSavingsInEffect = FALSE;

   /* Convert from UTC to Civil Time                           */

   civDateTime = utcDateTime + nTimeZoneOffsetInHours / 24.0;

   /* Adjust for Daylight Savings Time if Required             */

   if ( fUseDaylightSavingsTime )
      {

      /* Determine the UTC Year                                */

      JD2CAL ( utcDateTime, &nMonth, &nDay, &nYear, &nHour, &nMinute, &nSecond, &nMillisecond );

      /* Only Handle Years After 2007                          */

      if ( nYear < 2007 )
         return 0.0;

      /* Find Out When Daylight Savings Time Starts and Stops  */

      Year2DST ( nYear, nTimeZoneOffsetInHours, &utcBegDST, &utcEndDST );

      /* Handle the Daylight Savings Time Adjustment           */

      if ( utcDateTime >= utcBegDST && utcDateTime < utcEndDST )
         {
         if ( pfDaylightSavingsInEffect )
            * pfDaylightSavingsInEffect = TRUE;

         civDateTime += 1.0 / 24.0;
         }

      }  /* End - Adjust for Daylight Savings Time if Required */

   /* Return the Adjusted Time                                 */

   return civDateTime;

   }  /* double UTC2Civil ( double utcDateTime, BOOL * pfDaylightSavingsInEffect, int nTimeZoneOffsetInHours, BOOL fUseDaylightSavingsTime ) */

/* Convert from a Civil Date/Time Index to a UTC Date/Time Index and Tell Me if Daylight Savings Time Ambiguity */

double Civil2UTC ( double civDateTime, BOOL * pfDaylightSavingsAmbiguity, int nTimeZoneOffsetInHours, BOOL fUseDaylightSavingsTime )

   {
   double   utcDateTime = 0.0;
   int      nMonth = 0, nDay = 0, nYear = 0, nHour = 0, nMinute = 0, nSecond = 0, nMillisecond = 0;
   double   utcBegDST = 0.0, utcEndDST = 0.0;

   /* Default to No Ambiguity                                  */

   if ( pfDaylightSavingsAmbiguity )
      * pfDaylightSavingsAmbiguity = FALSE;

   /* Convert from Civil Time to UTC                           */

   utcDateTime = civDateTime - nTimeZoneOffsetInHours / 24.0;

   /* Adjust for Daylight Savings Time if Required             */

   if ( fUseDaylightSavingsTime )
      {

      /* Determine the UTC Year                                */

      JD2CAL ( civDateTime, &nMonth, &nDay, &nYear, &nHour, &nMinute, &nSecond, &nMillisecond );

      /* Only Handle Years After 2007                          */

      if ( nYear < 2007 )
         return 0.0;

      /* Find Out When Daylight Savings Time Starts and Stops  */

      Year2DST ( nYear, nTimeZoneOffsetInHours, &utcBegDST, &utcEndDST );

      /* Handle the Daylight Savings Time Adjustment           */

      if ( utcDateTime >= utcBegDST && utcDateTime < utcEndDST )
         {
         utcDateTime -= 1.0 / 24.0;

         if ( pfDaylightSavingsAmbiguity )
            {
            * pfDaylightSavingsAmbiguity = utcDateTime < ( utcBegDST + 1.0 / 24.0 ) || utcDateTime > ( utcEndDST - 1.0 / 24.0 );
            }
         }

      }  /* End - Adjust for Daylight Savings Time if Required */

   /* Return the Adjusted Time                                 */

   return utcDateTime;

   }  /* double Civil2UTC ( double civDateTime, BOOL * pfDaylightSavingsAmbiguity, int nTimeZoneOffsetInHours, BOOL fUseDaylightSavingsTime ) */

double CurrentTime ( void )

   {
   SYSTEMTIME stSystemTime = { 0 };

   GetSystemTime ( &stSystemTime );

   return CAL2JD ( stSystemTime.wMonth, stSystemTime.wDay, stSystemTime.wYear, stSystemTime.wHour, stSystemTime.wMinute, stSystemTime.wSecond, stSystemTime.wMilliseconds );

   }  /* double CurrentTime ( void ) */

/*
 * GetCivilTimeStamp takes a UTC Julian Day Number and Converts it into a TIMESTAMP_STRUCT for ODBC and SQL Server
 */

TIMESTAMP_STRUCT GetCivilTimeStamp ( double utcDateTime )

   {
   TIMESTAMP_STRUCT  stCivilTime    = { 0 };

   double            civDateTime    = 0.0;

   int               nMonth         = 0;
   int               nDay           = 0;
   int               nYear          = 0;
   int               nHour          = 0;
   int               nMinute        = 0;
   int               nSecond        = 0;
   int               nMillisecond   = 0;

   /* Convert the UTC Julian Day Number to a Civil Time Julian Day Number */

   civDateTime = UTC2Civil ( utcDateTime, NULL, -( _timezone / 3600L ), _daylight );

   /* Convert the Civil Time Julian Day Number into Months, Days, Years, Hours, Minutes, Seconds and Milliseconds */

   JD2CAL ( civDateTime, &nMonth, &nDay, &nYear, &nHour, &nMinute, &nSecond, &nMillisecond );

   /* Store the Date and Time into the TIMESTAMP_STRUCT */

   stCivilTime.month    = ( SQLUSMALLINT  ) nMonth;
   stCivilTime.day      = ( SQLUSMALLINT  ) nDay;
   stCivilTime.year     = ( SQLSMALLINT   ) nYear;
   stCivilTime.hour     = ( SQLUSMALLINT  ) nHour;
   stCivilTime.minute   = ( SQLUSMALLINT  ) nMinute;
   stCivilTime.second   = ( SQLUSMALLINT  ) nSecond;
   stCivilTime.fraction = ( SQLUINTEGER   ) ( nMillisecond * 1000000LU );

   /* Return the TIMESTAMP_STRUCT Representing the Date and Time as Civil Time */

   return stCivilTime;

   }  /* TIMESTAMP_STRUCT GetCivilTimeStamp ( STDISHSIGNALS & stDishSignals ) */

void DumpJD2UTC ( FILE * hFile, char * szLegend, double dblTimeUTC )

   {
   int nMo     = 0;
   int nDy     = 0;
   int nYear   = 0;
   int nHr     = 0;
   int nMn     = 0;
   int nSc     = 0;
   int nMs     = 0;

   JD2CAL ( dblTimeUTC, &nMo, &nDy, &nYear, &nHr, &nMn, &nSc, &nMs );

   fprintf ( hFile, "%s%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d GMT\n", szLegend, nMo, nDy, nYear, nHr, nMn, nSc, nMs ); 

   }  /* void DumpJD2UTC ( FILE * hFile, char * szLegend, double dblTime ) */

void DumpJD2Civ ( FILE * hFile, char * szLegend, double dblTimeUTC )

   {
   int   nMo   = 0;
   int   nDy   = 0;
   int   nYear = 0;
   int   nHr   = 0;
   int   nMn   = 0;
   int   nSc   = 0;
   int   nMs   = 0;

   BOOL fDST   = FALSE;

   /* Convert to Civil Time */

   if ( ! g_fTzSet )
      {
      _tzset();
      g_fTzSet = TRUE;
      }

   JD2CAL ( UTC2Civil ( dblTimeUTC, &fDST, -( _timezone / 3600L ), _daylight ), &nMo, &nDy, &nYear, &nHr, &nMn, &nSc, &nMs );

   fprintf ( hFile, "%s%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d %s\n", szLegend, nMo, nDy, nYear, nHr, nMn, nSc, nMs, fDST ? "MDT" : "MST" ); 

   }  /* void DumpJD2Civ ( FILE * hFile, char * szLegend, double dblTime ) */

char * myctime ( const time_t * plnTime )

   {
   static const char * pszMonth     []       = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jly", "Aug", "Sep", "Oct", "Nov", "Dec" };
   static const char * pszDayOfWeek []       = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
   static char       szTime         [ 26 ]   = { 0 };

   long              lnTime                  = * plnTime;
   long              gdNow                   = ( lnTime / 86400L ) + 719163L;
   double            dblTime                 = ( lnTime % 86400L ) / 86400.0;
   double            dblTimeUTC              = gdNow + dblTime + 1721424.5;

   int               nMo                     = 0;
   int               nDy                     = 0;
   int               nYear                   = 0;
   int               nHr                     = 0;
   int               nMn                     = 0;
   int               nSc                     = 0;
   int               nMs                     = 0;

   BOOL              fDST                    = FALSE;

   unsigned          uDayOfWeek              = 0U;

   /* Convert from UTC to Local Time */

   if ( ! g_fTzSet )
      {
      _tzset();
      g_fTzSet = TRUE;
      }

   JD2CAL ( UTC2Civil ( dblTimeUTC, &fDST, -( _timezone / 3600L ), _daylight ), &nMo, &nDy, &nYear, &nHr, &nMn, &nSc, &nMs );

   uDayOfWeek = MDY2GD ( nMo, nDy, nYear ) % 7L;

   /* Returned as "Mon Dec 15 19:41:22 2008\n\0" */

   _snprintf ( szTime, sizeof szTime, "%s %s %2d %2.2d:%2.2d:%2.2d %4.4d\n", pszDayOfWeek [ uDayOfWeek ], pszMonth [ nMo ], nDy, nHr, nMn, nSc, nYear );

   return szTime;

   }  /* char * myctime ( const time_t * plnTime ) */

main.cpp

/***************************************************************************************
*                                                                                      *
*  Copyright (c) 2010 David Cass Tyler, PO Box 1026, Willard, NM 87063, (505) 384-5342 *
*                                                                                      *
*  This program demonstrates using the Date and Time functions including converting    *
*  between UTC and Local Time.                                                         *
*                                                                                      *
*  Compile from the command line as:  "CL main.cpp DateTime.c"                         *
*                                                                                      *
*  Sample Output:                                                                      *
*                                                                                      *
*     F:\Projects\Website\DateTime>main                                                *
*     Tue Nov 23 11:00:03 2010                                                         *
*     UTC 11/23/2010 18:00:03.592 GMT                                                  *
*     Loc 11/23/2010 11:00:03.592 MST                                                  *
*     UTC 11/23/2010 18:00:03.592 GMT                                                  *
*     Original = 2455524.250042, Reconstructed = 2455524.250042                        *
*     Loc 11/23/2010 11:00:03.592 MST                                                  *
*     Res 11/23/2010 18:00:03.592 GMT                                                  *
*     SQL 11/23/2010 11:00:03.592                                                      *
*     11/23/2010 Today                                                                 *
*     10/31/2010 Last Day of Last Month                                                *
*     03/14/2010 2nd Sunday of March                                                   *
*                                                                                      *
*     F:\Projects\Website\DateTime>                                                    *
*                                                                                      *
***************************************************************************************/

// Try.cpp : Defines the entry point for the console application.
//

#include "DateTime.h"

main ( int /* argc */, char * /* argv */ [], char * /* envp */ [] )

   {

   // Print Out My Version of ctime

   time_t lnTimeNow = 0LU;

   time ( &lnTimeNow );

   fprintf ( stdout, myctime ( &lnTimeNow ) );

   // Dump the Time in both UTC and Civil Formats

   double   dblTimeUTC = CurrentTime();         // Get the Time as the Julian Day Number

   DumpJD2UTC ( stdout, "UTC ", dblTimeUTC );   // Dump the Time in UTC
   DumpJD2Civ ( stdout, "Loc ", dblTimeUTC );   // Dump the Time in Civil Time

   // Break the UTC Time into Component Parts and Print Them

   int nMo = 0, nDy = 0, nYear = 0, nHr = 0, nMn = 0, nSc = 0, nMs = 0;

   JD2CAL ( dblTimeUTC, &nMo, &nDy, &nYear, &nHr, &nMn, &nSc, &nMs );

   fprintf ( stdout, "UTC %2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d GMT\n", nMo, nDy, nYear, nHr, nMn, nSc, nMs );

   // Reverse that from Component Parts to Julian Day Number

   double dblReconstructed = CAL2JD ( nMo, nDy, nYear, nHr, nMn, nSc, nMs );

   fprintf ( stdout, "Original = %f, Reconstructed = %f\n", dblTimeUTC, dblReconstructed );

   // Get the Time Zone Information

   int      nTimeZoneOffsetInHours     = 0;
   BOOL     fUseDaylightSavingsTime    = FALSE;

   GetTzInfo ( &nTimeZoneOffsetInHours, &fUseDaylightSavingsTime );

   // Convert the UTC Time into Local Time

   BOOL     fDaylightSavingsInEffect   = FALSE;

   double   dblTimeLoc                 = UTC2Civil ( dblTimeUTC, &fDaylightSavingsInEffect, nTimeZoneOffsetInHours, fUseDaylightSavingsTime );

   char *   szTimeZoneName             = ( fDaylightSavingsInEffect ? "MDT" : "MST" );

   // Break the Local Time into Component Parts and Print Them

   JD2CAL ( dblTimeLoc, &nMo, &nDy, &nYear, &nHr, &nMn, &nSc, &nMs );

   fprintf ( stdout, "Loc %2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d %s\n", nMo, nDy, nYear, nHr, nMn, nSc, nMs, szTimeZoneName );

   // Return the Civil Time to UTC and Print It

   double dblRestored = Civil2UTC ( dblTimeLoc, NULL, nTimeZoneOffsetInHours, fUseDaylightSavingsTime );

   DumpJD2UTC ( stdout, "Res ", dblRestored );  // Dump the Time in UTC

   // Convert the Current UTC Time to a SQL Server TimeStamp and Print It

   TIMESTAMP_STRUCT stTimeStamp = GetCivilTimeStamp ( dblTimeUTC );

   fprintf (

      stdout,

      "SQL %2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d\n",

      stTimeStamp.month, stTimeStamp.day, stTimeStamp.year,
      stTimeStamp.hour, stTimeStamp.minute, stTimeStamp.second, stTimeStamp.fraction / 1000000

      );

   // Get Today's Gregorian Date Index

   long lnGregDateIndex = MDY2GD ( nMo, nDy, nYear );

   GD2MDY ( lnGregDateIndex, &nMo, &nDy, &nYear );

   fprintf ( stdout, "%2.2d/%2.2d/%4.4d Today\n", nMo, nDy, nYear );

   // Get the Last Day of Last Month

   JD2CAL ( dblTimeLoc, &nMo, &nDy, &nYear, &nHr, &nMn, &nSc, &nMs );

   lnGregDateIndex = MDY2GD ( nMo, 0, nYear );

   GD2MDY ( lnGregDateIndex, &nMo, &nDy, &nYear );

   fprintf ( stdout, "%2.2d/%2.2d/%4.4d Last Day of Last Month\n", nMo, nDy, nYear );

   // Get the 2nd Sunday of March of this Year

   JD2CAL ( dblTimeLoc, &nMo, &nDy, &nYear, &nHr, &nMn, &nSc, &nMs );

   lnGregDateIndex = MDY2GD ( nMo, 0, nYear );

   GD2MDY ( MDY2GD ( 3, 0, nYear ) / 7 * 7 + 14, &nMo, &nDy, &nYear );

   fprintf ( stdout, "%2.2d/%2.2d/%4.4d 2nd Sunday of March\n", nMo, nDy, nYear );

   return 0;

   }  // main ( int argc, char * argv [], char * envp [] )