/* $Revision: 25 $ $Date: 4/08/06 12:49 $ Copyright © 2000-2003, FSL Technologies Limited. Contact "http://fost3.fsltech.com". */ #include "stdafx.h" #include #define VC_EXTRALEAN #include #include #include #include #include #include #include #include using namespace std; using namespace FSLib; using namespace FSLib::Exceptions; namespace { Revision c_revision( L"$Archive: /FOST.3/F3Util/timedate.cpp $", __DATE__, L"$Revision: 25 $", L"$Date: 4/08/06 12:49 $" ); const wchar_t BadDateMsg[]=L"Invalid date."; const wchar_t BadTimeMsg[]=L"Invalid time."; const wchar_t BadTimeStampMsg[]=L"Invalid time stamp."; const wchar_t BadDatePeriodMsg[]=L"Invalid date period."; const wchar_t BadTimePeriodMsg[]=L"Invalid time period."; const Setting c_minyear( L"$Archive: $", L"Date and time", L"Min year", L"1901", true ); const Setting c_maxyear( L"$Archive: $", L"Date and time", L"Max year", L"2050", true ); } /* FSLib::Exceptions::BadDate */ inline BadDate::BadDate() { m_info << L"Date was not initialised." << std::endl; } inline BadDate::BadDate( int y, int m, int d ) { m_info << L"Date was (YYYY MM DD): " << y << L' ' << m << L' ' << d << std::endl; } inline BadDate::BadDate( const FSLib::wstring &s ) { m_info << L"Invalid date string: '" << s << L"'." << std::endl; } inline const wchar_t * const BadDate::message() const { return BadDateMsg; } /* FSLib::Exceptions::BadTime */ inline BadTime::BadTime() { m_info << L"Time was not initialised." << std::endl; } inline BadTime::BadTime( int h, int m, Time::t_seconds s ) { m_info << L"Time was (HH MM SS): " << h << L' ' << m << L' ' << s << std::endl; } inline BadTime::BadTime( const FSLib::wstring &s ) { m_info << L"Invalid time string: '" << s << L"'." << std::endl; } inline const wchar_t * const BadTime::message() const { return BadTimeMsg; } /* FSLib::Exceptions::BadTimeStamp */ inline BadTimeStamp::BadTimeStamp() { m_info << L"TimeStamp was not initialised." << std::endl; } inline BadTimeStamp::BadTimeStamp( int year, int month, int date, int h, int m, const Time::t_seconds &s ) { m_info << L"TimeStamp was ( YYYY MM DD - HH MM SS): " << year << L' ' << month << L' ' << date << L" - " << h << L' ' << m << L' ' << s << std::endl; } inline BadTimeStamp::BadTimeStamp( const FSLib::wstring &s ) { m_info << L"Invalid time stamp string: '" << s << L"'." << std::endl; } inline const wchar_t * const BadTimeStamp::message() const { return BadTimeStampMsg; } /* FSLib::Exceptions::BadDatePeriod */ BadDatePeriod::BadDatePeriod( const DatePeriod &dp ) { m_info << L"Date period is (Years Months Days): " << dp.years() << L' ' << dp.months() << L' ' << dp.days() << endl; } BadDatePeriod::BadDatePeriod( int y, int m, int d ) { m_info << L"Date period is (Years Months Days): " << y << L' ' << m << L' ' << d << endl; } BadDatePeriod::BadDatePeriod( const FSLib::wstring &s ) { m_info << L"Invalid date period string: " << s << endl << L"Correct format is 'Y9999M999D9999'" << endl; } inline const wchar_t * const BadDatePeriod::message() const { return BadDatePeriodMsg; } /* FSLib::Exceptions::BadTimePeriod */ BadTimePeriod::BadTimePeriod( const TimePeriod &tp ) { m_info << L"Time period was (Hours Minutes Seconds): " << tp.hours() << L' ' << tp.minutes() << L' ' << tp.seconds() << endl; } BadTimePeriod::BadTimePeriod( int h, int m, const Time::t_seconds &s ) { m_info << L"Time period was (Hours Minutes Seconds): " << h << L' ' << m << L' ' << s << endl; } BadTimePeriod::BadTimePeriod( const FSLib::wstring &s ) { m_info << L"Invalid time period string: " << s << endl; } BadTimePeriod::BadTimePeriod( const FSLib::wstring &e, unsigned __int64 ms ) : Exception( e ) { m_info << L"Milliseconds: 0x" << setbase( 16 ) << static_cast< unsigned long >( ms >> 16 ) << static_cast< unsigned long >( ms & 0xffffffff ) << setbase( 10 ) << endl; } inline const wchar_t * const BadTimePeriod::message() const { return BadTimePeriodMsg; } // Date - no time information inline Date::Date() : m_year( 0 ), m_month( 0 ), m_date( 0 ) { } inline Date::Date( const Date &d ) : m_year( d.m_year ), m_month( d.m_month ), m_date( d.m_date ) { } inline Date::Date( int y, int m, int d, bool doFixup ) : m_year( y ), m_month( m ), m_date( d ) { if ( doFixup ) { fixup(); } else { check(); } } inline Date::Date( const FSLib::wstring &s ) { if ( s.length() != 10 || ( s[4] != L'/' && s[4] != L'-' )|| ( s[7] != L'/' && s[7] != L'-' ) ) { throw BadDate( s ); } m_year = _wtoi( s.substr( 0, 4 ).c_str() ); m_month = _wtoi( s.substr( 5, 2 ).c_str() ); m_date = _wtoi( s.substr( 8, 2 ).c_str() ); check(); } inline bool Date::operator <( const Date &d ) const { valid(); return m_year < d.m_year || ( m_year == d.m_year && m_month < d.m_month ) || ( m_year == d.m_year && m_month == d.m_month && m_date < d.m_date ); } inline bool Date::operator <=( const Date &d ) const { return !( *this > d ); } inline bool Date::operator >( const Date &d ) const { valid(); return m_year > d.m_year || ( m_year == d.m_year && m_month > d.m_month ) || ( m_year == d.m_year && m_month == d.m_month && m_date > d.m_date ); } inline bool Date::operator >=( const Date &d ) const { return !( *this < d ); } inline bool Date::operator !=( const Date &t ) const { return operator <( t ) || operator >( t ); } inline bool Date::operator ==( const Date &t ) const { return !operator !=( t ); } inline Date Date::operator +( const DatePeriod &dp ) const { Date d( *this ); d += dp; return d; } inline Date &Date::operator +=( const DatePeriod &dp ) { m_year += dp.m_years; m_month += dp.m_months; m_date += dp.m_days; fixup(); return *this; } inline Date Date::operator -( const DatePeriod &dp ) const { Date d( *this ); d -= dp; return d; } inline Date &Date::operator -=( const DatePeriod &dp ) { m_year -= dp.m_years; m_month -= dp.m_months; m_date -= dp.m_days; fixup(); return *this; } inline FSLib::wstring Date::asString() const { return asString( L"-", L"-" ); } inline FSLib::wstring Date::asString( const FSLib::wstring &ym, const FSLib::wstring &md ) const { valid(); std::wstringstream s; s << m_year << ym << ( m_month < 10 ? L"0" : L"" ) << m_month << md << ( m_date < 10 ? L"0" : L"" ) << m_date; return s.str(); } inline FSLib::wstring Date::asStringUK( const FSLib::wstring &ym, const FSLib::wstring &md ) const { valid(); std::wstringstream s; s << ( m_date < 10 ? L"0" : L"" ) << m_date << ym << ( m_month < 10 ? L"0" : L"" ) << m_month << md << m_year; return s.str(); } inline FSLib::wstring Date::asString( int mask ) const { FSLib::wstring m, d( asString() ); if ( d.substr( 5, 2 ) == L"01" ) { m = L"January"; } else if ( d.substr( 5, 2 ) == L"02" ) { m = L"February"; } else if ( d.substr( 5, 2 ) == L"03" ) { m = L"March"; } else if ( d.substr( 5, 2 ) == L"04" ) { m = L"April"; } else if ( d.substr( 5, 2 ) == L"05" ) { m = L"May"; } else if ( d.substr( 5, 2 ) == L"06" ) { m = L"June"; } else if ( d.substr( 5, 2 ) == L"07" ) { m = L"July"; } else if ( d.substr( 5, 2 ) == L"08" ) { m = L"August"; } else if ( d.substr( 5, 2 ) == L"09" ) { m = L"September"; } else if ( d.substr( 5, 2 ) == L"10" ) { m = L"October"; } else if ( d.substr( 5, 2 ) == L"11" ) { m = L"November"; } else if ( d.substr( 5, 2 ) == L"12" ) { m = L"December"; } if ( mask ) { m = m.substr( 0, mask ); } return d.substr( 8, 2 ) + L' ' + m + L' ' + d.substr( 0, 4 ); } inline FSLib::wstring Date::asString( t_display display ) const { //defaults to e_sql switch ( display ) { case e_user_short: return asString( 3 ); case e_user_long: return asString( 0 ); case e_file_name: return asString( L"", L"" ); case e_user_uk: return asStringUK( L"/", L"/" ); default: return asString( L"-", L"-" ); } } Day Date::theDay() const { valid(); COleDateTime t( m_year, m_month, m_date, 0, 0, 0 ); int d( t.GetDayOfWeek() ); if ( d < 1 || d > 7 ) { throw BadDate(); } if ( d == 1 ) { return e_sunday; } else { return Day( d - 2 ); } } inline int Date::dayOfMonth() const { return m_date; } inline int Date::month() const { return m_month; } inline int Date::year() const { return m_year; } inline void Date::valid() const { if ( m_year == 0 && m_month == 0 && m_date == 0 ) { throw BadDate(); } } inline void Date::check() const { if ( m_year > _wtoi( c_maxyear.value().c_str() ) || m_year < _wtoi( c_minyear.value().c_str() ) || m_month > 12 || m_month < 1 || m_date > 31 || m_date < 1 ) throw BadDate( m_year, m_month, m_date ); } void Date::fixup() { m_year += ( m_month - 1 ) / 12; m_month = ( m_month - 1 ) % 12 + 1; while( m_month<=0 ) { m_month+=12; m_year--; } COleDateTime t( m_year, m_month, 1, 0, 0, 0 ); COleDateTimeSpan ts( m_date - 1, 0, 0, 0 ); t += ts; m_year = t.GetYear(); m_month = t.GetMonth(); m_date = t.GetDay(); } inline std::wostream &FSLib::operator <<( std::wostream &os, const Date &d ) { return os << d.asString(); } inline std::wostream &FSLib::operator <<( std::wostream &o, const Day d ) { switch ( d ) { case e_monday: return o << L"Monday"; case e_tuesday: return o << L"Tuesday"; case e_wednesday: return o << L"Wednesday"; case e_thursday: return o << L"Thursday"; case e_friday: return o << L"Friday"; case e_saturday: return o << L"Saturday"; case e_sunday: return o << L"Sunday"; default: return o << L"??"; } } // Time - no date information inline Time::Time() : m_hour( 0 ), m_minute( 0 ), m_second( -1 ) { } inline Time::Time( const Time &t ) : m_hour( t.m_hour ), m_minute( t.m_minute ), m_second( t.m_second ) { } inline Time::Time( int h, int m, t_seconds s, bool f ) : m_hour( h ), m_minute( m ), m_second( static_cast< int >( s * t_seconds( 1000 ) ) ) { if ( f ) { fixup(); } else { check(); } } inline Time::Time( const FSLib::wstring &t ) { if ( t.length() != 12 || t[2] != L':' || t[5] != L':' || t[8] != L'.' ) { throw BadTime( t ); } m_hour = _wtoi( t.substr( 0, 2 ).c_str() ); m_minute = _wtoi( t.substr( 3, 5 ).c_str() ); m_second = _wtoi( t.substr( 6, 8 ).c_str() ) * 1000 + _wtoi( t.substr( 9 ).c_str() ); check(); } inline Time::Time( const TimeStamp &ts ) : m_hour( ts.m_time.m_hour ), m_minute( ts.m_time.m_minute ), m_second( ts.m_time.m_second ) { check(); } inline bool Time::operator <( const Time &d ) const { return m_hour < d.m_hour || ( m_hour == d.m_hour && m_minute < d.m_minute ) || ( m_hour == d.m_hour && m_minute == d.m_minute && m_second < d.m_second ); } inline bool Time::operator <=( const Time &t ) const { return !operator >( t ); } inline bool Time::operator >( const Time &d ) const { return m_hour > d.m_hour || ( m_hour == d.m_hour && m_minute > d.m_minute ) || ( m_hour == d.m_hour && m_minute == d.m_minute && m_second > d.m_second ); } inline bool Time::operator >=( const Time &t ) const { return !operator <( t ); } inline bool Time::operator !=( const Time &t ) const { return operator <( t ) || operator >( t ); } inline bool Time::operator ==( const Time &t ) const { return !operator !=( t ); } inline int Time::hour() const { valid(); return m_hour; } inline int Time::minute() const { valid(); return m_minute; } inline Time::t_seconds Time::second() const { valid(); return static_cast< t_seconds >( m_second ) / 1000; } inline FSLib::wstring Time::asString() const { valid(); return asString( L":", L":", L"." ); } inline FSLib::wstring Time::asString( const FSLib::wstring &hm, const FSLib::wstring &ms, const FSLib::wstring &sms ) const { valid(); std::wstringstream s, secs; FSLib::wstring secstr; secs << m_second; secstr = FSLib::wstring( secs.str() ); while ( secstr.length() < 5 ) { secstr = L'0' + secstr; } s << ( m_hour < 10 ? L"0" : L"" ) << m_hour << hm << ( m_minute < 10 ? L"0" : L"" ) << m_minute << ms << secstr.substr( 0, 2 ) << sms << secstr.substr( 2 ); return s.str(); } inline FSLib::wstring Time::asString( t_display display ) const { valid(); switch ( display ) { case e_file_name: return asString( L"", L"", L"_" ).substr( 0, 6 ); case e_user_short: return asString( L":", L":", L"" ).substr( 0, 8 ); default: return asString( L":", L":", L"." ); } } inline Time &Time::addSeconds( const Time::t_seconds &s ) { valid(); m_second += static_cast< int >( s * 1000 ); fixup(); return *this; } inline void Time::valid() const { if ( m_hour == 0 && m_minute == 0 && m_second == -1 ) { throw BadTime(); } check(); } inline void Time::check() const { // We need to allow 24:00:00 as a valid time (e.g. FSLib::FSBilling::TimePeriod) if ( m_hour < 0 || ( m_hour > 23 && !( m_hour == 24 && m_minute == 0 && m_second == 0 ) ) || m_minute < 0 || m_minute > 59 || m_second < 0 || m_second >= 60000 ) { throw BadTime( m_hour, m_minute, m_second ); } } inline void Time::fixup() { long s( m_second / 1000 ); int h( s / 3600 ); m_hour += h; m_second -= h * 3600 * 1000; s = static_cast< long >( m_second / 1000 ); int m( s / 60 ); m_minute += m; m_second -= m * 60 * 1000; h = m_minute / 60; m_hour += h; m_minute -= h * 60; check(); } inline std::wostream &FSLib::operator <<( std::wostream &os, const Time &t ) { return os << t.asString(); } // TimeStamp - time with date information inline TimeStamp::TimeStamp() : m_date(), m_time() { } inline TimeStamp::TimeStamp( const TimeStamp &ts ) : m_date( ts.m_date ), m_time( ts.m_time ) { } inline TimeStamp::TimeStamp( int Y, int M, int D, int h, int m, Time::t_seconds s, bool fixup ) : m_date( Y, M, D, fixup ), m_time( h, m, s, fixup ) { } inline TimeStamp::TimeStamp( const Date &d, const Time &t ) : m_date( d ), m_time( t ) { // If we are constructing a time stamp from a time and a date then we must check to see // if we should roll over the 24:00:00 to midnight of the next day if ( m_time.hour() == 24 && m_time.minute() == 0 && m_time.second() == 0 ) { m_time.m_hour = 0; m_date += DatePeriod( L"Y0000M000D0001" ); } } inline TimeStamp::TimeStamp( const FSLib::wstring &s ) : m_date(), m_time() { if ( s.length() != 23 ) { throw BadTimeStamp( s ); } m_date = Date( s.substr( 0, 10 ) ); m_time = Time( s.substr( 11 ) ); } inline bool TimeStamp::operator <( const TimeStamp &t ) const { return ( m_date < t.m_date ) || ( m_date == t.m_date && m_time < t.m_time ); } inline bool TimeStamp::operator >( const TimeStamp &t ) const { return ( m_date > t.m_date ) || ( m_date == t.m_date && m_time > t.m_time ); } inline bool TimeStamp::operator !=( const TimeStamp &t ) const { return operator <( t ) || operator >( t ); } inline bool TimeStamp::operator ==( const TimeStamp &t ) const { return !operator !=( t ); } Time::t_seconds TimeStamp::operator -( const TimeStamp &t ) const { // GetTotalSeconds() does not work properly when subtraction result is negative if( *this == t ) { return 0; } else if( *this < t ) { return -( t - *this ); } else { return ( COleDateTime( m_date.m_year, m_date.m_month, m_date.m_date, m_time.m_hour, m_time.m_minute, static_cast< int >( m_time.m_second / 1000 ) ) - COleDateTime( t.m_date.m_year, t.m_date.m_month, t.m_date.m_date, t.m_time.m_hour, t.m_time.m_minute, static_cast< int >( t.m_time.m_second / 1000 ) ) ).GetTotalSeconds() + ( static_cast< Time::t_seconds >( ( m_time.m_second % 1000 ) - ( t.m_time.m_second % 1000 ) ) / 1000 ); } } inline TimeStamp TimeStamp::operator -( const DatePeriod &dp ) const { TimeStamp t( *this ); return t -= dp; } inline TimeStamp TimeStamp::operator -( const TimePeriod &tp ) const { TimeStamp t( *this ); return t -= tp; } inline TimeStamp TimeStamp::operator +( const DatePeriod &dp ) const { TimeStamp t( *this ); return t += dp; } inline TimeStamp TimeStamp::operator +( const TimePeriod &tp ) const { TimeStamp t( *this ); return t += tp; } TimeStamp &TimeStamp::operator -=( const DatePeriod &tp ) { m_date.m_year -= tp.m_years; m_date.m_month -= tp.m_months; while ( m_date.m_month < 1 ) { m_date.m_month += 12; m_date.m_year--; } COleDateTime t( m_date.m_year, m_date.m_month, m_date.m_date, m_time.m_hour, m_time.m_minute, static_cast< int >( m_time.m_second / 1000 ) ); COleDateTimeSpan ts( tp.m_days, 0, 0, 0 ); t -= ts; m_date.m_year = t.GetYear(); m_date.m_month = t.GetMonth(); m_date.m_date = t.GetDay(); return *this; } inline TimeStamp &TimeStamp::operator -=( const TimePeriod &tp ) { Time::t_seconds seconds( tp.hours() * 60 * 60 + tp.minutes() * 60 + tp.seconds() ); return addSeconds( -seconds ); } TimeStamp &TimeStamp::operator +=( const DatePeriod &tp ) { m_date.m_year += tp.m_years; m_date.m_month += tp.m_months; while ( m_date.m_month > 12 ) { m_date.m_month -= 12; m_date.m_year++; } COleDateTime t( m_date.m_year, m_date.m_month, m_date.m_date, m_time.m_hour, m_time.m_minute, static_cast< int >( m_time.m_second / 1000. ) ); COleDateTimeSpan ts( tp.m_days, 0, 0, 0 ); t += ts; m_date.m_year = t.GetYear(); m_date.m_month = t.GetMonth(); m_date.m_date = t.GetDay(); return *this; } inline TimeStamp &TimeStamp::operator +=( const TimePeriod &tp ) { Time::t_seconds seconds( tp.hours() * 60 * 60 + tp.minutes() * 60 + tp.seconds() ); return addSeconds( seconds ); } inline Day TimeStamp::theDay() const { return m_date.theDay(); } inline const Date &TimeStamp::theDate() const { return m_date; } inline const Time &TimeStamp::theTime() const { return m_time; } inline FSLib::wstring TimeStamp::asString() const { return m_date.asString() + L' ' + m_time.asString(); } inline FSLib::wstring TimeStamp::asString( t_display display ) const { switch ( display ) { case e_file_name: return m_date.asString( Date::e_file_name ) + L'_' + m_time.asString( Time::e_file_name ); default: return asString(); } } TimeStamp &TimeStamp::addSeconds( Time::t_seconds s ) { COleDateTime ole( m_date.m_year, m_date.m_month, m_date.m_date, m_time.m_hour, m_time.m_minute, static_cast< int >( m_time.m_second / 1000. ) ); int sec, m, h, d; sec = static_cast< long >( s ); d = sec / ( 60 * 60 * 24 ); sec = sec % ( 60 * 60 * 24 ); h = sec / ( 60 * 60 ); sec = sec % ( 60 * 60 ); m = sec / 60; sec = sec % 60; ole += COleDateTimeSpan( d, h, m, sec ); m_date.m_year = ole.GetYear(); m_date.m_month = ole.GetMonth(); m_date.m_date = ole.GetDay(); m_time.m_hour = ole.GetHour(); m_time.m_minute = ole.GetMinute(); m_time.m_second = ole.GetSecond() * 1000 + ( int( s * 1000 ) % 1000 ); return *this; } TimeStamp TimeStamp::now() { SYSTEMTIME time; GetSystemTime( &time ); return TimeStamp( time.wYear, time.wMonth, time.wDay, time.wHour, time.wMinute, static_cast< Time::t_seconds >( time.wSecond ) + time.wMilliseconds / 1000. ); } inline std::wostream &FSLib::operator <<( std::wostream &os, const TimeStamp &t ) { return os << t.asString(); } /* TimePeriod */ inline TimePeriod::TimePeriod() : m_hours( -1 ), m_minutes( -1 ), m_seconds( -1 ) { } inline TimePeriod::TimePeriod( const TimePeriod &tp ) : m_hours( tp.m_hours ), m_minutes( tp.m_minutes ), m_seconds( tp.m_seconds ) { } inline TimePeriod::TimePeriod( unsigned __int64 ms ) : m_hours( -1 ), m_minutes( -1 ), m_seconds( -1 ) { if ( ms > ( static_cast< unsigned __int64 >( 9999 * 3600 ) + 59 * 60 + 59 ) * 1000 ) { throw BadTimePeriod( L"Too many milliseconds", ms ); } m_seconds = static_cast< double >( static_cast< signed __int64 >( ms % 60000 ) ) / 1000; m_minutes = static_cast< int >( ( ms / 60000 ) % 60 ); m_hours = static_cast< int >( ms / ( 60000 * 60 ) ); } inline TimePeriod::TimePeriod( const FSLib::wstring &s ) : m_hours( -1 ), m_minutes( -1 ), m_seconds( -1 ) { if ( s.length() != 15 || s[ 4 ] != L'h' || s[ 7 ] != L'm' || s[ 10 ] != L'.' || s[ 14 ] != L's' ) { throw BadTimePeriod( s ); } m_hours = _wtoi( s.substr( 0, 4 ).c_str() ); m_minutes = _wtoi( s.substr( 5, 7 ).c_str() ); m_seconds = _wtoi( s.substr( 8, 10 ).c_str() ); m_seconds += _wtoi( s.substr( 11, 14 ).c_str() ) / 1000.; } inline TimePeriod::TimePeriod( int hours, int minutes, Time::t_seconds seconds ) : m_hours( hours ), m_minutes( minutes ), m_seconds( seconds ) { if ( m_hours < 0 || m_minutes < 0 || m_seconds < 0 ) throw BadTimePeriod( m_hours, m_minutes, m_seconds ); else if ( m_hours > 9999 || m_minutes > 99 || m_seconds > 99 ) throw BadTimePeriod( m_hours, m_minutes, m_seconds ); } inline FSLib::wstring TimePeriod::asString() const { if ( m_hours < 0 || m_minutes < 0 || m_seconds < 0 ) { throw BadTimePeriod( m_hours, m_minutes, m_seconds ); } wstringstream s; s << setfill( L'0' ) << setw( 4 ) << m_hours << L"h" << setw( 2 ) << m_minutes << L"m" << setw( 2 ) << static_cast< int >( m_seconds ) << L"." << setw( 3 ) << ( static_cast< int >( m_seconds * 1000 ) % 1000 ) << L"s"; return s.str(); } inline unsigned __int64 TimePeriod::milliseconds() const { return static_cast< unsigned __int64 >( m_hours ) * 3600 * 1000 + static_cast< unsigned __int64 >( m_minutes ) * 60 * 1000 + static_cast< unsigned __int64 >( m_seconds * 1000 ); } inline bool TimePeriod::operator <( const FSLib::TimePeriod &t ) const { return milliseconds() < t.milliseconds(); } inline int TimePeriod::hours() const { return m_hours; } inline int TimePeriod::minutes() const { return m_minutes; } inline Time::t_seconds TimePeriod::seconds() const { return m_seconds; } inline std::wostream &FSLib::operator <<( std::wostream &os, const TimePeriod &t ) { return os << t.asString(); } /* DatePeriod */ inline DatePeriod::DatePeriod() : m_years( -1 ), m_months( -1 ), m_days( -1 ) { } inline DatePeriod::DatePeriod( const DatePeriod &dp ) : m_years( dp.m_years ), m_months( dp.m_months ), m_days( dp.m_days ) { } inline DatePeriod::DatePeriod( const FSLib::wstring &s ) : m_years( -1 ), m_months( -1 ), m_days( -1 ) { if ( s.length() != 14 || s[ 0 ] != L'Y' || s[ 5 ] != L'M' || s[ 9 ] != L'D' ) { throw BadDatePeriod( s ); } m_years = _wtoi( s.substr( 1, 5 ).c_str() ); m_months = _wtoi( s.substr( 6, 9 ).c_str() ); m_days = _wtoi( s.substr( 10 ).c_str() ); } inline DatePeriod::DatePeriod( int years, int months, int days ) : m_years( years ), m_months( months ), m_days( days ) { if ( years < 0 || years > 9999 ) throw FSLib::Exceptions::OutOfRange< int >( L"Number of years is outside allowed range", 0, 10000, years ); if ( months < 0 || months > 999 ) throw FSLib::Exceptions::OutOfRange< int >( L"Number of months is outside allowed range", 0, 1000, months ); if ( days < 0 || days > 9999 ) throw FSLib::Exceptions::OutOfRange< int >( L"Number of days is outside allowed range", 0, 10000, days ); if ( years ==0 && months == 0 && days == 0 ) throw FSLib::Exceptions::BadDatePeriod( L"Not all of years, months and days may be zero." ); } inline FSLib::wstring DatePeriod::asString() const { if ( m_years < 0 || m_months < 0 || m_days < 0 ) { throw BadDatePeriod( m_years, m_months, m_days ); } wstringstream s; s << setfill( L'0' ) << L'Y' << setw( 4 )<< m_years << L'M' << setw( 3 ) << m_months << L'D' << setw( 4 ) << m_days; return s.str(); } inline bool DatePeriod::operator <( const DatePeriod &d ) const { return asString() < d.asString(); } inline bool DatePeriod::operator >( const DatePeriod &d ) const { return asString() > d.asString(); } inline bool DatePeriod::operator !=( const DatePeriod &t ) const { return asString() != t.asString(); } inline std::wostream &FSLib::operator <<( std::wostream &os, const DatePeriod &t ) { return os << t.asString(); } /* $History: timedate.cpp $ * * ***************** Version 25 ***************** * User: Kirit Date: 4/08/06 Time: 12:49 * Updated in $/FOST.3/F3Util * Corrected bug in TimeStamp::addSeconds() which was losing the * milliseconds. * * ***************** Version 24 ***************** * User: Kirit Date: 4/08/06 Time: 11:36 * Updated in $/FOST.3/F3Util * Attempt to get fractional seconds working properly. * * ***************** Version 23 ***************** * User: Kirit Date: 26/10/05 Time: 19:55 * Updated in $/FOST.3/F3Util * Altered Date format to be ISO compatible (replaced slashes with * dashes). * * ***************** Version 22 ***************** * User: Kirit Date: 25/08/05 Time: 13:21 * Updated in $/FOST.3/F3Util * Added operator <() for FSLib::TimePeriod * * ***************** Version 21 ***************** * User: Kirit Date: 21/04/05 Time: 16:48 * Updated in $/FOST.3/F3Util * Added some items to TimePeriod to help with the HTML interface. * * ***************** Version 20 ***************** * User: Kirit Date: 26/03/05 Time: 20:36 * Updated in $/FOST.3/F3Util * * Debugged editing of a new FSLib::Time * * Debugged display of menu items where item is dynamic but not * understood * * ***************** Version 19 ***************** * User: Kirit Date: 26/03/05 Time: 13:34 * Updated in $/FOST.3/F3Util * * GUI now knows how to handle DatePeriod attributes. * * Moved userString to be part of HTML generation. * * ***************** Version 18 ***************** * User: Kirit Date: 9/10/03 Time: 15:44 * Updated in $/FOST.3/F3Util * Headers re-arranged to give a proper SDK feel and to make determination * of required headers simpler. * * ***************** Version 16 ***************** * User: Kirit Date: 8/10/03 Time: 12:48 * Updated in $/FOST/Cpp/FSCppUtil * Removed WINVER settings. * * ***************** Version 15 ***************** * User: Kirit Date: 3/10/03 Time: 18:44 * Updated in $/FOST.3/F3Util * * ***************** Version 14 ***************** * User: Kirit Date: 3/10/03 Time: 16:09 * Updated in $/FOST/Cpp/FSCppUtil * Added stdafx.h and stdafx.cpp pre-compiled header support. * * ***************** Version 13 ***************** * User: Kirit Date: 20/07/03 Time: 22:23 * Updated in $/FOST/Cpp/FSCppUtil * Copy constructors (for braindead compiler error) and comparison * operators for DatePeriod. * * ***************** Version 12 ***************** * User: Kirit Date: 7/05/02 Time: 12:01 * Updated in $/FOST/Cpp/FSCppUtil * Wrapped std::basic_string<> in order to change the copy semantics to * stop the problems with using C++ in the COM layer for IIS. * * ***************** Version 11 ***************** * User: Kirit Date: 19/03/02 Time: 20:54 * Updated in $/FOST/Cpp/FSCppUtil * Corrected history from last check-in. * Updated TestAX.IDL to remove registry entries from removed classes. * * ***************** Version 10 ***************** * User: Kirit Date: 19/03/02 Time: 19:48 * Updated in $/FOST/Cpp/FSCppUtil * Debug compiles now all end in '_d'. * The C++ implementation names (Type.cppName) have been changed to also * include the DLL that the implementation is in as per the documentation. * In all source files the following have been done: * * Ensured that every header file has a revision object. * * Ensured that every translation unit has a revision object. * * Ensured that every source file (which understands comments) * has a history section. * * Changed all copyright notices to be for Obsideon Ltd. * * Changed copyright notices to use the longest possible timeframe. * * ***************** Version 9 ***************** * User: Kirit Date: 25/12/01 Time: 19:12 * Updated in $/FOST/Cpp/FSCppUtil * Some debugging of and extension of TimePeriod. * Added new reporting to Task and sorted out synchronised access to its * data members. * * ***************** Version 8 ***************** * User: Kirit Date: 24/12/01 Time: 15:20 * Updated in $/FOST/Cpp/FSCppUtil * Minor corrections to exceptions and some constructors. * * ***************** Version 7 ***************** * User: Kirit Date: 4/11/01 Time: 22:09 * Updated in $/FOST/Cpp/FSCppUtil * Switch to UTC time rather than local time. * * ***************** Version 6 ***************** * User: Kirit Date: 23/10/01 Time: 22:54 * Updated in $/FOST/FSCppUtil * Added new members to allow more complete arithmetic on TimeStamps. * * ***************** Version 5 ***************** * User: Kirit Date: 5/07/01 Time: 17:41 * Updated in $/FOST/FSCppUtil * First Unicode only version of FOST. * * ***************** Version 4 ***************** * User: Kirit Date: 2/07/01 Time: 14:19 * Updated in $/FOST/FSCppUtil * Addition of FSSettings DLL to handle simple default setting values. * * ***************** Version 3 ***************** * User: Kirit Date: 28/06/01 Time: 19:21 * Updated in $/FOST/FSCppUtil * Added millisecond support to Time::t_seconds TimeStamp::operator -( * const TimeStamp & ) const. * * ***************** Version 2 ***************** * User: Kirit Date: 26/06/01 Time: 17:30 * Updated in $/FOST/FSCppUtil * Time & Date library working. */