// // TIMEDATE.CPP // // Source file for ArchiveLib 1.0 // // Copyright (c) Greenleaf Software, Inc. 1994 // All Rights Reserved // // CONTENTS // // ALTimeDate::operator new() // ALTimeDate::ALTimeDate() // ALTimeDate::~ALTimeDate() // ALTimeDate::ToJulian() // ALTimeDate::FromJulian() // ALTimeDate::GetUnixTime() // ALTimeDate::SetTimeDate(long) // ALTimeDate::SetTimeDate(struct tm *) // ALTimeDate::GetTimeDate() // // DESCRIPTION // // This file contains all of the member functions of class ALTimeDate. // This class is used only by ALStorage, but it seemed like a good // idea to break it out in a separate class. A lot of the code in here // came straight out of CommLib. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // // #include "arclib.h" #pragma hdrstop #include #include "timedate.h" // // void * ALTimeDate::operator new( size_t size ) // // ARGUMENTS: // // size : The number of bytes needed to create a new ALTimeDate object. // // RETURNS // // A pointer to the newly allocated storage area, or 0 if no storage // was available. // // DESCRIPTION // // When using a DLL, it is easy to get into a dangerous situation when // creating objects whose ctor and dtor are both in the DLL. The problem // arises because when you create an object using new, the memory for // the object will be allocated from the EXE. However, when you destroy // the object using delete, the memory is freed inside the DLL. Since // the DLL doesn't really own that memory, bad things can happen. // // But, you say, won't the space just go back to the Windows heap regardless // of who tries to free it? Maybe, but maybe not. If the DLL is using // a subsegment allocation scheme, it might do some sort of local free // before returning the space to the windows heap. That is the point where // you could conceivably cook your heap. // // By providing our own version of operator new inside this class, we // ensure that all memory allocation for the class will be done from // inside the DLL, not the EXE calling the DLL. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // #if defined( AL_BUILDING_DLL ) void AL_DLL_FAR * AL_PROTO ALTimeDate::operator new( size_t size ) { return ::new char[ size ]; } #endif // // ALTimeDate::ALTimeDate() // // ARGUMENTS: // // None. // // RETURNS // // None. // // DESCRIPTION // // All the constructor does is initialize the data members. By // setting the year to an invalid value of 0, we can always see // that the time date stamp for a file hasn't been initialized. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // AL_PROTO ALTimeDate::ALTimeDate() { miYear = 0; //This is an illegal year, means it is uninitialized miMonth = 0; miDate = 0; miHour = 0; miMinute = 0; miSecond = 0; } // // ALTimeDate::~ALTimeDate() // // ARGUMENTS: // // None. // // RETURNS // // None. // // DESCRIPTION // // The destructor has nothing to do. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // AL_PROTO ALTimeDate::~ALTimeDate() { } // // long ALTimeDate::ToJulian() // // ARGUMENTS: // // None. // // RETURNS // // A Julian day. // // DESCRIPTION // // This function is used to make a Julian day number from a normal // month/day/year thing. We need a Julian day in order to make a // UNIX style time stamp. The UNIX time stamp is used to store // time stamps in Archive directories. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // long AL_PROTO ALTimeDate::ToJulian() { return (long)( miDate - 32076) + 1461L * ( miYear + 4800L + ( miMonth - 14) / 12) / 4 + 367 * ( miMonth - 2 - ( miMonth - 14) / 12 * 12) / 12 - 3 * (( miYear + 4900L + ( miMonth - 14) / 12) / 100) / 4 + 1; } // // void ALTimeDate::FromJulian( long jdn ) // // ARGUMENTS: // // jdn : A julian date number, ideally one produced by ToJulian(). // // RETURNS // // Nothing. // // DESCRIPTION // // This function is used to convert a julian date to a normal // year/month/day. Time/date stamps are stored in Archives in // UNIX format. This function is needed to convert a UNIX // time stamp to a normal mm/dd/yy. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // void AL_PROTO ALTimeDate::FromJulian( long jdn ) { long x; long z; long m; long d; long y; const long daysPer400Years = 146097L; const long fudgedDaysPer4000Years = 1460970L + 31; x = jdn + 68569L; z = 4 * x / daysPer400Years; x = x - (daysPer400Years * z + 3) / 4; y = 4000 * (x + 1) / fudgedDaysPer4000Years; x = x - 1461 * y / 4 + 31; m = 80 * x / 2447; d = x - 2447 * m / 80; x = m / 11; m = m + 2 - 12 * x; y = 100 * (z - 49) + y + x; // // I don't know whether or not we could eliminate these temporary longs // miYear = (short int) y; miMonth = (short int) m; miDate = (short int) d; } // // long ALTimeDate::GetUnixTime() // // ARGUMENTS: // // None. // // RETURNS // // A UNIX time, converted from the internal m/d/y h:m:s data. // // DESCRIPTION // // This function is used to convert the m/d/y h:m:s time stamp for a file // into a UNIX time stamp. The UNIX time stamp is a 32 bit long that // is used to store time stamps in an Archive. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // long AL_PROTO ALTimeDate::GetUnixTime() { const long UnixFirstDay = 2440588L; long result; result = ToJulian(); result -= UnixFirstDay; if ( result >= 0L ) { result *= 3600L * 24; result += 3600L * miHour; result += 60L * miMinute; result += miSecond; } else result = 0L; return result; } // // void ALTimeDate::SetTimeDate( long unix_time ) // // ARGUMENTS: // // unix_time : A long integer in UNIX timestamp format. // // RETURNS // // Nothing. // // DESCRIPTION // // This function is called when we are reading a directory in from // an archive. It is used to set the internal data members of an // ALTimeDate object, after converting from unix time. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // void AL_PROTO ALTimeDate::SetTimeDate( long unix_time ) { const long UnixFirstDay = 2440588L; long jd = unix_time / ( 3600L * 24 ); long hms = unix_time % ( 3600L * 24 ); FromJulian( jd + UnixFirstDay ); miHour = (short int) ( hms / 3600 ); hms -= 3600L * miHour; miMinute = (short int) ( hms / 60 ); miSecond = (short int) ( hms - ( miMinute * 60 ) ); } // // void ALTimeDate::SetTimeDate( struct tm *tblock ) // // ARGUMENTS: // // tblock : A time date stamp as used by the C run time library. // // RETURNS // // Nothing. // // DESCRIPTION // // When working with DOS files, time stamps are read in to a structure // in the struct tm format. This function provides an easy way to convert // the structure into our internal format. When a DOS file is opened // using Open(), this function is called. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // void AL_PROTO ALTimeDate::SetTimeDate( struct tm AL_DLL_FAR *tblock ) { AL_ASSERT( tblock != 0, "SetTimeDate: passing illegal null parameter" ); miYear = (short int) ( tblock->tm_year + 1900 ); miMonth = (short int) ( tblock->tm_mon + 1 ); miDate = (short int) tblock->tm_mday; miHour = (short int) tblock->tm_hour; miMinute = (short int) tblock->tm_min; miSecond = (short int) tblock->tm_sec; } // // void ALTimeDate::GetTimeDate( struct tm *tblock ) // // ARGUMENTS: // // tblock : A structure in the format used by the C runtime library for // storing time and date stamps. // // RETURNS // // Nothing. // // DESCRIPTION // // This function provides the reverse of SetTimeDate(). You would think // that we could just set the appropriate members of struct tm, but // there is a problem with that. struct tm has one element that is // supposed to be the day of the week, and another that is supposed // to be the number of the day within the year. We could try to // figure those out using the julian day function, but since gmtime() // will figure them out for us, we'll use that instead. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // void AL_PROTO ALTimeDate::GetTimeDate( struct tm AL_DLL_FAR *tblock ) { AL_ASSERT( tblock != 0, "GetTimeDate: passing illegal null parameter" ); long unix_time = GetUnixTime(); struct tm *result = gmtime( (const time_t *) &unix_time ); if ( result ) { *tblock = *result; tblock->tm_isdst = 0; } else { //This should never happen! tblock->tm_year = miYear - 1900; tblock->tm_mon = miMonth - 1; tblock->tm_mday = miDate; tblock->tm_hour = miHour; tblock->tm_min = miMinute; tblock->tm_sec = miSecond; tblock->tm_wday = 0; tblock->tm_yday = 0; tblock->tm_isdst = 0; } } // // unsigned short int ALTimeDate::GetDosTime() // // ARGUMENTS: // // None. // // RETURNS // // This function returns the time stored in this. The bits of the // time are packed into the form that is needed by the _dos_setftime() // format. // // DESCRIPTION // // When we close a file that needs to have its time and date stamp // set, we normally use the _dos_setftime() function to do the // work. It expects to see the time packed into a particular // sequence of bits in an unsigned short. That is what this // function does. It packs the bits just the way you want them. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // #if !defined( AL_WIN32S ) unsigned short int AL_PROTO ALTimeDate::GetDosTime() { int result; result = miSecond / 2; result |= miMinute << 5; result |= miHour << 11; return (unsigned short int) result; } #endif //#if !defined( AL_WIN32S ) // // unsigned short int ALTimeDate::GetDosDate() // // ARGUMENTS: // // None. // // RETURNS // // This function returns the date stored in this object. The bits of the // date are packed into the form that is needed by the _dos_setftime() // format. // // DESCRIPTION // // When we close a file that needs to have its time and date stamp // set, we normally use the _dos_setftime() function to do the // work. It expects to see the date packed into a particular // sequence of bits in an unsigned short. That is what this // function does. It packs the bits just the way you want them. // // REVISION HISTORY // // May 26, 1994 1.0A : First release // #if !defined( AL_WIN32S ) unsigned short int AL_PROTO ALTimeDate::GetDosDate() { int result; result = miDate; result |= miMonth << 5; result |= (miYear-1980) << 9; return (unsigned short int ) result; } #endif //#if !defined( AL_WIN32S )