Visual Studio C++ Libraries DateTimeMillisecond

From Minor Miracle Software
Revision as of 13:53, 27 February 2021 by WikiSysop (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

DateTimeMillisecond.h

// ************************************************************************* //
// Filename:                                                                 //
//  DateTimeMillisecond.h - Header file.                                     //
//                                                                           //
// Description:                                                              //
//  Date/Time Keeping class for Win32 with millisecond accuracy. All times   //
//  are UTC.                                                                 //
//                                                                           //
// Authors:                                                                  //
//  JBD  Jesse B. Dooley                                                     //
//                                                                           //
// Date:                                                                     //
//   February 24, 2021                                                       //
// Assumptions:                                                              //
// 1. All times are UTC. Mixing Local Time, Daylight Savings Time, and UTC   //
//    provides too much opportunity for errors.                              //
// Edits:                                                                    //
// 1. Added int GetWeekOfYear() const;                                       //
// 2. Added // Ordinal Week Of Year                                          //
//            int WOY_int;                                                   //
// ************************************************************************* //

// ************************************************************************* //
// COleDateTime is used for conversions because it is UTC time.
// COleDateTime converts a SYSTEMTIME to DayOfYear
// * Default time is December 30, 1899, midnight.
// ************************************************************************* //

// ************************************************************************* //
// CTime is used to produce total seconds because:
// * Default time is January 1, 1970, midnight.
// ************************************************************************* //


// ************************************************************************* //
// __time64_t variables are initialized with time(&) or gmtime(&) as the 
// seconds since midnight on January 1, 1970.
// 
// The difference in seconds between gmttime(&) and COleDateTime is
// 2209161600.
// ************************************************************************* //

// ************************************************************************* //

/*

 typedef struct _SYSTEMTIME { 
   WORD wYear; 
   WORD wMonth; 
   WORD wDayOfWeek; 
   WORD wDay; 
   WORD wHour; 
   WORD wMinute; 
   WORD wSecond; 
   WORD wMilliseconds; 
} SYSTEMTIME;

    wYear         = The current year. The valid values for this member are 1601 through 30827.
    wMonth        = The current month; January is 1, December is 12.
    wDayOfWeek    = The current day of the week; Sunday is 0, Monday is 1, and so on.
    wDay          = The current day of the month. 1-31.
    wHour         = The current hour. 0-23.
    wMinute       = The current minute. 0-59.
    wSecond       = The current second. 0-59.
    wMilliseconds = The current millisecond. 0-999.

    DOY is an independent variable.

    CTime uses localtime
    COleDateTime uses UTC.
 */

#ifndef _DateTimeMillisecond_
#define _DateTimeMillisecond_

#include <SDKDDKVer.h>
#include "stdafx.h"
#include <time.h>
#include <ostream>
#include <math.h>
#include <stdint.h>
#include <ATLComTime.h>
#include <ctime>

#include "DateTimeMillisecondSpan.h"

enum DateTimeMillisecondStatus
{
    error = -1,
    valid = 0,
    invalid = 1, // Invalid date (out of range, etc.)
    null = 2     // Literally has no value, default value
};

class DateTimeMillisecond {
    
public:
    // Set to January 1, 1970 at midnight
    DateTimeMillisecond(); 
    DateTimeMillisecond( SYSTEMTIME t );
    DateTimeMillisecond( COleDateTime d );
    DateTimeMillisecond( time_t  d );
    DateTimeMillisecond( CString );

    // Set time in Seconds and Milliseconds since January 1, 1970 at midnight
    DateTimeMillisecond( __time64_t sec, int32_t millisecond ); 

    virtual ~DateTimeMillisecond();

    void Now(); // set to now

        // Return m_status value
    DateTimeMillisecondStatus GetStatus();
    bool IsValid(); // is the date valid?

    void Set( SYSTEMTIME );
    void Set( int year_int, int doy_int, int hour_int, int minute_int, int second_int, int millisecond_int );
    // Returns true if the result is a valid datetime
    bool Set( CString );
    // Print Methods
    int DOYTimeTagPrint (char* const where, size_t len);
    CString DOYTimeTagPrint ();
    CString YearTimeTagPrint();

    // Is Daylight Savings Time in effect? true or false
    static bool IsDaylightSavingsTime(); 

// Distribution Methods
    static bool IsLeapYear( );
    static bool IsLeapYear( int year_int );

    SYSTEMTIME Get();
    __time64_t GetTotalSeconds() const;
    int GetYear() const;
    // Month of year (1 = January)
    int GetMonth() const;
    // Month of year (1 = January)
    CString GetMonthName();
    // Day of month (1-31)
    int GetDayOfMonth() const;
    // Hour in day (0-23)
    int GetHour() const;
    // Minute in hour (0-59)
    int GetMinute() const;
    // Second in minute (0-59)
    int GetSecond() const;
    // Day of week (1 = Sunday, 2 = Monday, ..., 7 = Saturday)
    int GetDayOfWeek() const;
    // Day of week (1 = Sunday, 2 = Monday, ..., 7 = Saturday)
    CString GetDayOfWeekName();
    // Days since start of year (1 = January 1)
    int GetDayOfYear() const;
    // Ordinal week numbered 1-53.
    int GetWeekOfYear() const;
    // milliseconds since Second
    int GetMillisecond() const;
    // Fetch as "DOY HH:MM:SS.ms", milliseconds to two places
    CString TimeStamp();
    // Fetch as "YYYY-DOY HH:MM:SS"
    CString TimeOfDay();
    // Fetch as "YYYY-DOY HH:MM:SS.sss"
    CString TimeOfDayLong();
    // Fetch as "MM:SS.ss"
    CString ShortTimeStamp();

// operator overloads for DateTimeMillisecond
    bool operator==( const DateTimeMillisecond& rhs) ;
    void operator=( const DateTimeMillisecond& rhs);
    bool operator>( const DateTimeMillisecond& rhs) const;
    bool operator>=( const DateTimeMillisecond& rhs) const;
    bool operator<( const DateTimeMillisecond& rhs) const;
    bool operator<=( const DateTimeMillisecond& rhs) const;

    operator double ( ) const
    {
        //cout<<"Converting a TimeSpec to a double."<<endl;
        return double( GetTotalSeconds() )+double( GetMillisecond())*1.0e-3;
    }


// operator overloads with DateTimeMillisecondSpan
    DateTimeMillisecondSpan operator- ( const DateTimeMillisecond& date) const;
    DateTimeMillisecond operator-=( const DateTimeMillisecondSpan& date) const;
    DateTimeMillisecond& operator+= ( const DateTimeMillisecondSpan& a);

private:
// Day Of Year
    int DOY_int;
// Ordinal Week Of Year
    int WOY_int;
// Is the stored date valid?
    DateTimeMillisecondStatus m_status;
// Primary time storage
    SYSTEMTIME this_systemtime;
// Get ISO 8601 week count. 1-53.
// Always set this_systemtime first
    int GetWeekNumber();
    static int ComputeDOY (int year_int, int month_int, int day_int);
    static int ComputeMonth (int year_int, int doy_int);
    static int ComputeDay (int year_int, int doy_int);

};
#endif

DateTimeMillisecond.cpp

// ************************************************************************* //
// Filename:                                                                 //
//  DateTimeMillisecond.cpp - Code file.                                     //
//                                                                           //
// Description:                                                              //
//  Date/Time Keeping class for Win32 with millisecond accuracy. All times   //
//  are UTC.                                                                 //
//                                                                           //
// Authors:                                                                  //
//  JBD  Jesse B. Dooley                                                     //
//                                                                           //
// Date:                                                                     //
//   Feburary 24, 2021                                                       //
// Assumptions:                                                              //
// 1. All times are UTC. Mixing Local Time, Daylight Savings Time, and UTC   //
//    provides too much opportunity for errors.                              //
// Edits:                                                                    //
// 1. Added int GetWeekOfYear() const;                                       //
// ************************************************************************* //

// ************************************************************************* //
// COleDateTime is used for conversions because it is UTC time.
// COleDateTime converts a SYSTEMTIME to DayOfYear
// * Default time is December 30, 1899, midnight.
// ************************************************************************* //

// ************************************************************************* //
// CTime is used to produce total seconds because:
// * Default time is January 1, 1970, midnight.
// ************************************************************************* //

#include "DateTimeMillisecond.h"

DateTimeMillisecond::DateTimeMillisecond() {

    this_systemtime.wYear = 1970;
    this_systemtime.wHour = 0;
    this_systemtime.wMonth = 1; 
    this_systemtime.wDayOfWeek = 4; 
    this_systemtime.wDay = 1; 
    this_systemtime.wMinute = 0; 
    this_systemtime.wSecond = 0; 
    this_systemtime.wMilliseconds = 0;
    DOY_int = 1;
    WOY_int = 1;

    m_status = null;
}

// Set time in Seconds and Milliseconds
// Daylight Savings Time Safe
DateTimeMillisecond::DateTimeMillisecond( __time64_t sec, int32_t millisecond ) {
    // Negative time is not supported
    if( sec < 0 || millisecond < 0 ) {
        m_status = invalid;
        return;
    }
    // Rollover
    DateTimeMillisecondSpan Rollover_dtms = DateTimeMillisecondSpan( sec, millisecond );
    sec = Rollover_dtms.GetTotalSeconds();
    millisecond = Rollover_dtms.GetMilliseconds();

    // If in Daylight Savings Time fall back one hour
    if( IsDaylightSavingsTime() == true ) 
        sec -= 3600;

    // Convert sec to COleDateTime
    COleDateTime cdt = COleDateTime( sec );

    // Test for successful convertion
    if( cdt.GetAsSystemTime( this_systemtime ) == true ) {
        m_status = valid;
        DOY_int = cdt.GetDayOfYear();
        WOY_int = GetWeekNumber ();  // always set this_systemtime first
        this_systemtime.wMilliseconds = millisecond;
    } else {
        m_status = invalid;
    }
}

// Daylight Savings Time Safe
DateTimeMillisecond::DateTimeMillisecond( SYSTEMTIME t )
    :this_systemtime(t)
{
    DOY_int = ComputeDOY ( t.wYear, t.wMonth, t.wDay );
    ValidateTest();
}

// COleDateTime has no millisecond variable. That is set to zero.
// Daylight Savings Time Safe
DateTimeMillisecond::DateTimeMillisecond( COleDateTime d ) {
    if ( d.GetStatus() == valid ) {
        if(    d.GetAsSystemTime( this_systemtime ) == true ) {
            DOY_int = d.GetDayOfYear();
            WOY_int = GetWeekNumber ();  // always set this_systemtime first
            m_status = valid;
        }
    } else {
        m_status = invalid;
    }
}

// time_t is a __time64_t, it does not contain milliseconds
// Daylight Savings Time Safe
DateTimeMillisecond::DateTimeMillisecond( time_t  d ) {
    // valid date if not nullptr
    struct tm buff;
    if( localtime_s( &buff, &d ) == 0 ) {
        // If in Daylight Savings Time fall back one hour
        if( IsDaylightSavingsTime() == true ) 
            d -= 3600;
        COleDateTime cdt_d = COleDateTime ( d );
        DOY_int = cdt_d.GetDayOfYear();
        WOY_int  = GetWeekNumber ();  // always set this_systemtime first
        cdt_d.GetAsSystemTime( this_systemtime );
        m_status = valid;
    } else {
        m_status = error;
    }
}

DateTimeMillisecond::~DateTimeMillisecond() {}

// Daylight Savings Time Safe
void DateTimeMillisecond::Now() { // set to now
    GetSystemTime(&this_systemtime);
    if( ValidateTest() == true ) {
        DOY_int = ComputeDOY ( this_systemtime.wYear, this_systemtime.wMonth, this_systemtime.wDay );
        WOY_int  = GetWeekNumber ();  // always set this_systemtime first
    }
}

DateTimeMillisecondStatus DateTimeMillisecond::GetStatus( ) {
    return m_status;
}

// Is the current object valid?
// This tests the SYSTEMTIME struct
// this_systemtime is not changed
bool DateTimeMillisecond::IsValid( ) {
    COleDateTime test_time = COleDateTime( this_systemtime );
    if( test_time.GetStatus() == valid ) {
        m_status = valid;
        return true;
    } 
    this.DateTimeMillisecond(); // reset
    m_status = invalid;
    return false;
}


// Daylight Savings Time Safe
void DateTimeMillisecond::Set( SYSTEMTIME sys_t ) {
    DateTimeMillisecond dtm_test = DateTimeMillisecond( sys_t );
    // validate SYSTEMTIME sys_t
    if( dtm_test.ValidateTest() == true ) {
        this_systemtime = sys_t;
        DOY_int = ComputeDOY ( this_systemtime.wYear, this_systemtime.wMonth, this_systemtime.wDay );
        WOY_int  = GetWeekNumber ();  // always set this_systemtime first
        m_status = valid;
    } else {
        m_status = error;
    }
}

// Daylight Savings Time Safe
void DateTimeMillisecond::Set( int year_int, int doy_int, int hour_int, int minute_int, int second_int, int millisecond_int ) {
    // Use a COleDateTime for conversion and validation
    int month_int = ComputeMonth( year_int, doy_int) + 1;
    int dayofmonth_int = ComputeDay( year_int, doy_int );
    COleDateTime time_in = COleDateTime( year_int,
        month_int,
        dayofmonth_int,
        hour_int,
        minute_int,
        second_int );
    // Check for a valid date
    if( time_in.GetStatus() == valid ) {
        time_in.GetAsSystemTime( this_systemtime );
        this_systemtime.wMilliseconds = millisecond_int;
        DOY_int = doy_int;
        WOY_int  = GetWeekNumber ();  // always set this_systemtime first
        m_status = valid;
    } else {
        m_status = error;
    }
}


// Parses a datetime string and ignored milliseconds
// 
bool DateTimeMillisecond::Set( CString Date_cs ) {
    COleDateTime Date_cdt;
    Date_cdt.ParseDateTime( Date_cs, LOCALE_NOUSEROVERRIDE );
    SYSTEMTIME sysTime;
    Date_cdt.GetAsSystemTime( sysTime );
    Set( sysTime );
    return IsValid();
}

SYSTEMTIME DateTimeMillisecond::Get() {
    return this_systemtime;    
}

// Converts DateTimeMillisecond to seconds since
// January 1, 1970, midnight.
// The default DateTimeMillisecond should return zero.
__time64_t DateTimeMillisecond::GetTotalSeconds() const {
    // test for a valid date
    if( m_status == valid ) {
        CTime ct_sample = CTime( this_systemtime, 0 );
        return ct_sample.GetTime();
    } 
    return 0;
}

// If the system is on daylight savings time return true
// else return false.
// 0 = TIME_ZONE_ID_UNKNOWN
// 1 = TIME_ZONE_ID_STANDARD
// 2 = TIME_ZONE_ID_DAYLIGHT
bool DateTimeMillisecond::IsDaylightSavingsTime() {
    TIME_ZONE_INFORMATION TimeZoneInformation = {0};
    DWORD TZ_result = GetTimeZoneInformation( &TimeZoneInformation );
    return (TZ_result == TIME_ZONE_ID_DAYLIGHT);
}


// distribution methods
int DateTimeMillisecond::GetYear() const {
    return this_systemtime.wYear;
}
// Month of year (1 = January)
int DateTimeMillisecond::GetMonth() const {
    return this_systemtime.wMonth;
}
CString DateTimeMillisecond::GetMonthName() {
    switch( this_systemtime.wMonth ) {
        case 1: return "January";
        case 2: return "February";
        case 3: return "March";
        case 4: return "April";
        case 5: return "May";
        case 6: return "June";
        case 7: return "July";
        case 8: return "August";
        case 9: return "September";
        case 10: return "October";
        case 11: return "November";
        case 12: return "December";
    }
    return "";
}
// Day of month (1-31)
int DateTimeMillisecond::GetDayOfMonth() const {
    return this_systemtime.wDay;
}
// Hour in day (0-23)
int DateTimeMillisecond::GetHour() const {
    return this_systemtime.wHour;
}
// Minute in hour (0-59)
int DateTimeMillisecond::GetMinute() const {
    return this_systemtime.wMinute;
}
// Second in minute (0-59)
int DateTimeMillisecond::GetSecond() const {
    return this_systemtime.wSecond;
}
// Day of week (1 = Sunday, 2 = Monday, ..., 7 = Saturday)
int DateTimeMillisecond::GetDayOfWeek() const {
    return this_systemtime.wDayOfWeek;
}
// Day of week (1 = Sunday, 2 = Monday, ..., 7 = Saturday)
CString DateTimeMillisecond::GetDayOfWeekName( ) {
    switch( this_systemtime.wDayOfWeek ) {
        case 0: return "Sunday";
        case 1: return "Monday";
        case 2: return "Tuesday";
        case 3: return "Wednesday";
        case 4: return "Thursday";
        case 5: return "Friday";
        case 6: return "Saturday";
    };
    return "";
}

// Days since start of year (1 = January 1)
int DateTimeMillisecond::GetDayOfYear() const {
    COleDateTime d = COleDateTime( this_systemtime );
    return d.GetDayOfYear();
}
    // Ordinal week numbered 1-53.
int DateTimeMillisecond::GetWeekOfYear() const {
    return WOY_int;
}

// milliseconds since Second
int DateTimeMillisecond::GetMillisecond() const {
    return this_systemtime.wMilliseconds;
}
// Fetch as "DOY HH:MM:SS.ms", milliseconds to two places
CString DateTimeMillisecond::TimeStamp() {
    CString return_cs;
        // DOY HH:MM:SS.ss
    if( m_status == valid ) {
        // The date is valid
        return_cs.Format( "%03d %02u:%02u:%02u.%03u",
            DOY_int,
            this_systemtime.wHour,
            this_systemtime.wMinute,
            this_systemtime.wSecond,
            this_systemtime.wMilliseconds);
    } else {
        // The date is invalid, return all zeros
        return_cs.Format( "%03d %02d:%02d:%02d.%03d",
            0,
            0,
            0,
            0,
            0);
    }

    return return_cs;
}
// Fetch as "YYYY-DOY HH:MM:SS"
CString DateTimeMillisecond::TimeOfDay() {
    CString return_cs;
        // YYYY-DOY HH:MM:SS
    if( m_status == valid ) {
        // The date is valid
        return_cs.Format( "%04u-%03d %02u:%02u:%02u",
            this_systemtime.wYear,
            DOY_int,
            this_systemtime.wHour,
            this_systemtime.wMinute,
            this_systemtime.wSecond);
    } else {
        // The date is invalid, return all zeros
        return_cs.Format( "%04d-%03d %02d:%02d:%02d",
            0,
            0,
            0,
            0,
            0);
    }
    return return_cs;
}
// Fetch as "YYYY-DOY HH:MM:SS.sss"
CString DateTimeMillisecond::TimeOfDayLong() {
    CString return_cs;
        // YYYY-DOY HH:MM:SS.sss
    if( m_status == valid ) {
        // The date is valid
        return_cs.Format( "%04u-%03d %02u:%02u:%02u.%03u",
            this_systemtime.wYear,
            DOY_int,
            this_systemtime.wHour,
            this_systemtime.wMinute,
            this_systemtime.wSecond,
            this_systemtime.wMilliseconds );
    } else {
        // The date is invalid, return all zeros
        return_cs.Format( "%04d-%03d %02d:%02d:%02d.%03d",
            0,
            0,
            0,
            0,
            0,
            0);
    }
    return return_cs;
}

// Fetch as "MM:SS.sss"
CString DateTimeMillisecond::ShortTimeStamp() {
    CString return_cs;
        // MM:SS.sss
    if( m_status == valid ) {
        // The date is valid
        return_cs.Format( "%02u:%02u.%03u",
            this_systemtime.wMinute,
            this_systemtime.wSecond,
            this_systemtime.wMilliseconds);
    } else {
        // The date is invalid, return all zeros
        return_cs.Format( "%02d:%02d.%03d",
            0,
            0,
            0);
    }

    return return_cs;
}

// operator overloads
bool DateTimeMillisecond::operator==( const DateTimeMillisecond& rhs)  {
    if( this->GetTotalSeconds() == rhs.GetTotalSeconds() &&
        this->GetMillisecond() == rhs.GetMillisecond() )
        return true;
    else
        return false;
}

void DateTimeMillisecond::operator=( const DateTimeMillisecond& rhs) 
{
    Set( rhs.this_systemtime );
}

DateTimeMillisecond DateTimeMillisecond::operator-=( const DateTimeMillisecondSpan& rhs) const {

    __time64_t this_total = this->GetTotalSeconds();
    __time64_t result_total = this_total -= rhs.GetTotalSeconds();
    int32_t this_mill = this->GetMillisecond();
    int32_t result_mill = this_mill -= rhs.GetMilliseconds();

    return DateTimeMillisecond( result_total, result_mill );
}



// Used to add one DateTimeMillisecond timespan to another
DateTimeMillisecond& DateTimeMillisecond::operator+=( const  DateTimeMillisecondSpan& rhs) {
    
    __time64_t this_total = this->GetTotalSeconds();
    __time64_t result_total = this_total += rhs.GetTotalSeconds();
    int32_t this_mill = this->GetMillisecond();
    int32_t result_mill = this_mill += rhs.GetMilliseconds();

    *this =  DateTimeMillisecond( result_total, result_mill );
    return *this;
}

DateTimeMillisecondSpan DateTimeMillisecond::operator-( const DateTimeMillisecond& rhs) const {

    __time64_t result_total = this->GetTotalSeconds() - rhs.GetTotalSeconds();
    int32_t result_mill = this->GetMillisecond() - rhs.GetMillisecond();

    return DateTimeMillisecondSpan( result_total, result_mill );    
}

bool DateTimeMillisecond::operator>( const DateTimeMillisecond& rhs) const {

    if( this->GetTotalSeconds() > rhs.GetTotalSeconds() )
        return true;
    else if( this->GetTotalSeconds() == rhs.GetTotalSeconds() &&
        this->GetMillisecond() > rhs.GetMillisecond() )
        return true;

    return false;
}

bool DateTimeMillisecond::operator>=( const DateTimeMillisecond& rhs) const {

    if( this->GetTotalSeconds() >= rhs.GetTotalSeconds() )
        return true;
    else if( this->GetTotalSeconds() == rhs.GetTotalSeconds() &&
        this->GetMillisecond() >= rhs.GetMillisecond() )
        return true;

    return false;
}

bool DateTimeMillisecond::operator<=( const DateTimeMillisecond& rhs) const {

    if( this->GetTotalSeconds() <= rhs.GetTotalSeconds() )
        return true;
    else if( this->GetTotalSeconds() == rhs.GetTotalSeconds() &&
        this->GetMillisecond() <= rhs.GetMillisecond() )
    return true;

    return false;
}

bool DateTimeMillisecond::operator<( const DateTimeMillisecond& rhs) const {

    if( this->GetTotalSeconds() < rhs.GetTotalSeconds() )
        return true;
    else if( this->GetTotalSeconds() == rhs.GetTotalSeconds() &&
        this->GetMillisecond() < rhs.GetMillisecond() )
    return true;

    return false;
}

// is the stored year a leap year.
bool DateTimeMillisecond::IsLeapYear( ) {
    return IsLeapYear( this_systemtime.wYear );

}
// given an integer year return true if leapyear or false otherwise
bool DateTimeMillisecond::IsLeapYear( int year_int ) {
    // If February 29 is valid for the given year,
    // return true, else return false.
    // Microsoft months are 1-12
    COleDateTime testdate;
    if( testdate.SetDate( year_int, 2, 29 ) == 0)
        return true;
    else
        return false;
}

int DateTimeMillisecond::ComputeDOY (int year_int, int month_int, int day_int) {
    // Microsoft months are 1-12
    // GMT months are 0-11
    COleDateTime DOYdate;
    if( DOYdate.SetDate( year_int, month_int, day_int ) == 1)
        return -1;

    return DOYdate.GetDayOfYear();
}

/////////////////////////////////////////////////////////////////////////
// Given year and doy return 0 based month
//
int DateTimeMillisecond::ComputeMonth (int year_int, int doy_int) {
    int l_count = 0;
    int leap_int = 0;

    if (IsLeapYear (year_int))
    {
        leap_int = 1;
    }
    else
    {
        leap_int = 0;
    }

    if( doy_int < 1 || doy_int > 365 + leap_int )
        return -1;

    if ( leap_int == 1 )
    {
        int l_Mdays [] = {1,31,60,91,121,152,182,213,244,274,305,335,366};
        for (l_count = 0; l_count < 12; l_count++)
        {
            if ( doy_int >= l_Mdays[l_count] && doy_int <= l_Mdays[l_count + 1 ] )
            {
                return l_count;
            }
        }
    }
    else
    {
        int l_Mdays [] = {1,31,59,90,120,151,181,212,243,273,304,334,365};
        for (l_count = 0; l_count < 12; l_count++)
        {
            if ( doy_int >= l_Mdays[l_count] && doy_int <= l_Mdays[l_count + 1 ] )
            {
                return l_count;
            }
        }
    }
    return -1;
}

// Computes the day of an event's occurrence from the year, month, and day-of-year
int DateTimeMillisecond::ComputeDay (int year_int, int doy_int) {
    int leap_int = 0;
    // Month is zero based
    int month_int = ComputeMonth( year_int, doy_int);

    // Test for leap year
    if (IsLeapYear (year_int))
    {
        leap_int = 1;
    }
    else
    {
        leap_int = 0;
    }

    // Test for month range
    if( month_int < 0  )
        return -1;
    // Test for day range
    if( doy_int < 1 || doy_int > 365 + leap_int )
        return -1;

    if ( leap_int == 1 )
    {
        // Test for January
        if( month_int == 0 ) {
            return doy_int;
        }
        else
        {
            int l_Mdays [] = {31,60,91,121,152,182,213,244,274,305,335,366};
            return doy_int - l_Mdays[ month_int - 1 ];
        }
    }
    else
    {
        // Test for January
        if( month_int == 0 ) {
            return doy_int;
        }
        else
        {
            int l_Mdays [] = {31,59,90,120,151,181,212,243,273,304,334,365};
            return doy_int - l_Mdays[ month_int - 1 ];
        }
    }
    return -1;
}

CString  DateTimeMillisecond::YearTimeTagPrint() {
    CString return_cs;

    if( m_status == valid ) {
        // The date is valid
         return_cs.Format( "%04d %03d %02d:%02d:%02d.%01d",
            GetYear(),
            GetDayOfYear(),
            GetHour(),
            GetMinute(),
            GetSecond(),
            GetMillisecond() );
    } else {
        // The date is invalid, return all zeros
        return_cs.Format("%04d %03d %02d:%02d:%02d.%01d",
            0,
            0,
            0,
            0,
            0,
            0);
    }
    return return_cs;

}

// char* const version
int DateTimeMillisecond::DOYTimeTagPrint (char* const where, size_t len) {
    if( m_status == valid ) {
        // The date is valid
        return ::sprintf_s(where,len,"%d %02d:%02d:%02d.%01d",
            GetDayOfYear(),
            GetHour(),
            GetMinute(),
            GetSecond(),
            GetMillisecond() );
    } else {
        // The date is invalid, return all zeros
        return ::sprintf_s(where,len,"%d %02d:%02d:%02d.%01d",
            0,
            0,
            0,
            0,
            0);
    }
    return 0;
}

// CString version
CString DateTimeMillisecond::DOYTimeTagPrint () {
    CString cs;
    if( m_status == valid ) {
        // The date is valid
        cs.Format( "%d %02d:%02d:%02d.%01d",
            GetDayOfYear(),
            GetHour(),
            GetMinute(),
            GetSecond(),
            GetMillisecond() );
    } else {
        // The date is invalid, return all zeros
        cs.Format("%d %02d:%02d:%02d.%01d",
            0,
            0,
            0,
            0,
            0);
    }
    return cs;
}

// Private Methods
// Always set this_systemtime first
int DateTimeMillisecond::GetWeekNumber ( ) {
    struct tm tm_t;
    char timebuf[64];

    // Zero out struct tm
    memset(&tm_t, 0, sizeof tm);
    tm_t.tm_sec = this_systemtime.wSecond;
    tm_t.tm_min = this_systemtime.wMinute;
    tm_t.tm_hour = this_systemtime.wHour;
    tm_t.tm_mday = this_systemtime.wDay;
    tm_t.tm_mon = this_systemtime.wMonth;
    tm_t.tm_year = this_systemtime.wYear;
    tm_t.tm_isdst = -1;

    // Call mktime to recompute tm.tm_wday and tm.tm_yday
    mktime(&tm);
    // %V returns an ISO 8601 week number
    if (strftime(timebuf, sizeof timebuf, "%V", &tm_t) != 0) {
       printf("Week number is: %s\n", timebuf);
        try {
            return std::stoi(timebuf);
        } catch (std::exception const &e) {
            // This could not be parsed into a number so an exception is thrown.
            // atoi() would return 0, which is less helpful if it could be a valid value.
            return -1;
        }
    } else {
      return -1;
    }
}

Internal Links

Parent Article: Visual Studio C++ Libraries