XDate
XDate includes implementation of the classesCGregorianDate, CIsoDate, and CFiscalDate. Please click on the following links for more information:
- CGregorianDate: manipulating dates in the Gregorian calendar
- CIsoDate: manipulating ISO-8601 dates; and XDateCalc, a calculator to display Gregorian and ISO dates
- CFiscalDate: manipulating fiscal dates, weeks, quarters, and years; and XFisCal, a program that lets you create a printable fiscal calendar
CFiscalDate
A fiscal year is an accounting period of 52 weeks that may not coincide with the calendar year that begins on January 1st. An organization establishes a fiscal year in order to define begin and end dates for its annual financial records. A fiscal year is numbered according to the date of the calendar year in which it ends. Examples:- The financial operations of the U.S. federal government are carried out in a fiscal year that begins on October 1 and ends on September 30; the U.S. government's fiscal year for 2009 began on October 1, 2008 and will end on September 30, 2009.
- The fiscal year of the Canadian federal and provincial governments is April 1 to March 31; the Canadian government's fiscal year for 2010 began on April 1, 2009 and will end on March 31, 2010.
The fiscal year is divided into fiscal quarters, each 13 weeks long. The 13 weeks are grouped into months, according to one of three patterns: 5-4-4, 4-5-4, or 4-4-5. It is common to number the weeks within a quarter consecutively, from 1 to 13, just like the weeks in a fiscal year are numbered from 1 to 52.
CFiscalDate implements a class for manipulating fiscal dates, weeks, quarters, and years.
This is a very common requirement for businesses and government organizations, both for budgetary and scheduling purposes.
Wikipedia discusses many aspects of fiscal calendars, and the different formats used around the world. Here are the key points which any attempt to implement fiscal calendar software must be able to accommodate:
- Non-standard start date - the fiscal year could start on a month or day besides January 1.
- First day of the week - the week could begin on a Sunday or Monday.
- First week of the fiscal year - this could be either the week that contains January 1st (for example), or it could be the first full week following January 1st.
XDate.h can handle all of these variations. There are two qualifications: first, every fiscal quarter must be composed of 13 weeks; and second, every fiscal year must be composed of 52 weeks. These two conditions are sometimes called the 4-4-5 or 5-4-4 calendar, for the 13 weeks per quarter.
XDate.h
The file XDate.h includes implementation of the classesCGregorianDate, CIsoDate, and CFiscalDate. This article discusses CFiscalDate; Parts 1 and 2 discuss
CGregorianDate and CIsoDate.
At the end of this article, there is a list of
CFiscalDate class members.
CFiscalDate data members are:
//=============================================================================
// Data
//=============================================================================
public:
enum eFiscalWeekOne { START_WEEK_INCLUDES_START_DAY = 0, STARTS_ON_FIRST_FULL_WEEK };
private:
// Note that all w-d-y values are one-based.
// data in/out
int fiscal_week_of_quarter; // 1..13
int fiscal_quarter; // 1..4
int fiscal_year; // 1583..INT_MAX; note that this is always the
// Gregorian year in which the fiscal year ENDS
// fiscal year options
int start_month; // 1..12
int start_day; // 1..LastDayOfMonth()
eFiscalWeekOne eWeek; // default = START_WEEK_INCLUDES_START_DAY
int week_start_day; // 0..6; 0 = Monday
int week_end_day; // 0..6; 0 = Monday
CGregorianDate fiscal_quarters[4]; // quarter start dates
CFiscalDate has constructors for the following date types:
CGregorianDateSYSTEMTIMEtime_t
CFiscalDate Construction
Examples of CFiscalDate construction:
-
Default construction
// start on Jan 1, first week includes start day, // weeks starts on Sunday CFiscalDate fd; fd.Set(4, 1, 2009); // set to week 1 of Q4 of FY2009 -
Construction from current time
CFiscalDate fd(CFiscalDate::GetCurrentTime()); or CFiscalDate fd = CFiscalDate::GetCurrentTime(); -
Construction from Gregorian date MM/DD/YYYY
CFiscalDate fd; fd.SetFromGregorian(3, 17, 2009); -
Construction from CGregorianDate object
CGregorianDate gd(3, 17, 2009); CFiscalDate fd(gd); or CIsoDate fd; fd = gd; -
Construction from SYSTEMTIME
SYSTEMTIME st; GetLocalTime(&st); CFiscalDate fd(st); -
Construction from time_t
time_t t; time(&t); CFiscalDate fd(t);
CFiscalDate Usage
To useCFiscalDate, you first need to determine the settings for the fiscal year. If you used the default constructor, these settings would be:
start_month = 1; // January
start_day = 1; // 1st of the month
eWeek = START_WEEK_INCLUDES_START_DAY; // 1st week of year includes start_day;
// alternative is to begin on 1st full week
week_start_day = 6; // weeks begins on Sunday;
// alternative is Monday (0)
Example: Set to a Fiscal Date
Set the CFiscalDate object to 1st week of 4th quarter, 2009:
CFiscalDate fd;
fd.Set(4, 1, 2009);
Example: Get the Gregorian Date
You can get the Gregorian date from the aboveCFiscalDate object like this:
int m, d, y;
fd.GetGregorian(m, d, y);
The variables m, d, y now contain 9-27-2009, or September 27, 2009;
the first day of the week is always returned when converting to Gregorian.
Example: Get FY 2009 Fiscal Quarter Start Dates
// from XDateTestDlg.cpp
CFiscalDate fd1;
for (i = 1; i <= 4; i++)
{
fd1.Set(i, 1, 2009);
fd1.GetGregorian(m, d, y);
m_List.Printf(CXListBox::Black, CXListBox::White, 0,
_T(" Q%d'09 starts on %d/%d/%d"), i, m, d, y);
}
The above code produces this output:
Q1'09 starts on 12/28/2008
Q2'09 starts on 3/29/2009
Q3'09 starts on 6/28/2009
Q4'09 starts on 9/27/2009
Example: Get FY 2009 Q4 Week Start Dates
// from XDateTestDlg.cpp
CFiscalDate fd1;
for (i = 0; i < 13; i++)
{
fd1.Set(4, i+1, 2009);
fd1.GetGregorian(m, d, y);
m_List.Printf(CXListBox::Black, CXListBox::White, 0,
_T(" Q4'09 week %2d starts on %d/%d/%d"), i+1, m, d, y);
}
The above code produces this output:
Q4'09 week 1 starts on 9/27/2009
Q4'09 week 2 starts on 10/4/2009
Q4'09 week 3 starts on 10/11/2009
Q4'09 week 4 starts on 10/18/2009
Q4'09 week 5 starts on 10/25/2009
Q4'09 week 6 starts on 11/1/2009
Q4'09 week 7 starts on 11/8/2009
Q4'09 week 8 starts on 11/15/2009
Q4'09 week 9 starts on 11/22/2009
Q4'09 week 10 starts on 11/29/2009
Q4'09 week 11 starts on 12/6/2009
Q4'09 week 12 starts on 12/13/2009
Q4'09 week 13 starts on 12/20/2009
Example: Get Fiscal Week from Gregorian Date
// from XDateTestDlg.cpp
CFiscalDate fd1;
for (i = 0; i < 13; i++)
{
fd1.SetFromGregorian(dataset5[i].m, dataset5[i].d, dataset5[i].y);
m_List.Printf(CXListBox::Black, CXListBox::White, 0,
_T(" %2d/%02d/%d falls in Q%d'%02d week %2d"),
dataset5[i].m, dataset5[i].d, dataset5[i].y,
fd1.GetQuarter(), fd1.GetYearWithoutCentury(), fd1.GetWeekOfYear());
}
The above code produces this output:
9/27/2009 falls in Q4'09 week 40
10/04/2009 falls in Q4'09 week 41
10/11/2009 falls in Q4'09 week 42
10/18/2009 falls in Q4'09 week 43
10/25/2009 falls in Q4'09 week 44
11/01/2009 falls in Q4'09 week 45
11/08/2009 falls in Q4'09 week 46
11/15/2009 falls in Q4'09 week 47
11/22/2009 falls in Q4'09 week 48
11/29/2009 falls in Q4'09 week 49
12/06/2009 falls in Q4'09 week 50
12/13/2009 falls in Q4'09 week 51
12/20/2009 falls in Q4'09 week 52
Please see XDateTestDlg.cpp for more examples of how to use CFiscalDate.
CFiscalDate Debugging
CFiscalDate provides the following debugging facilities:
-
virtual void Trace(LPCTSTR lpszMsg = NULL) const - This virtual function can be called anytime to write the week, day, and year, along with an optional message, to
OutputDebugString(). The non-MFC XTrace.h is used to write the output when_DEBUGis defined, just like MFC's TRACE. To enable this, un-comment the line that is highlighted below://============================================================================= // TRACE output //============================================================================= // if you want to see the TRACE output, uncomment this line: //#define XDATE_ENABLE_TRACE #undef TRACE_XDATE #ifdef XDATE_ENABLE_TRACE #include "XTrace.h" // non-MFC TRACE #define TRACE_XDATE TRACE #else #define TRACE_XDATE __noop #endif -
virtual void AssertValid() const - This virtual function can be called anytime to verify the date and display a diagnostic message via
_ASSERTE(when_DEBUGis defined). - virtual void Dump() const - This virtual function may be overriden to provide custom debug output.
If you want to use the CFiscalDate Trace facility, don't forget to un-comment the line shown above, and also include XTrace.h in your project directory.
XDateTest
The demo application XDateTest.exe tests the various features and APIs of the XDate classes:
XFisCal
The demo application XFisCal.exe lets you create a printable HTML fiscal calendar:
The settings shown above produce this calendar:
Note that this calendar began in 2008, but is called fiscal year 2009 because that is the year it ends in.
XFisCal.exe creates the calendar as a HTML file. You can take this file and modify it to meet your needs. It uses the css file XFisCal.css, which is stored as a resource inside XFisCal.exe, and written to the destination folder (this happens only once, if it does not already exist). Since it uses only standard HTML, it is easy to view and print from any browser. It is also easy to email to someone - be sure to send both the .html and XFisCal.css files.
XFisCal Implementation Details
The css file XFisCal.css is stored inside XFisCal.exe as resourceIDU_CSSFILE.
Using the CResourceFile class, it is extracted and written to the file XFisCal.css; see CXFisCalDlg::CreateCssFile()to examine the code for doing this.
The default location for the css file and the HTML output file is
- C:\Documents and Settings\<user name>\Application Data\HDSoft\XFisCal
At the beginning of XFisCalDlg.cpp, you will see the main blocks of HTML that are written to the generated HTML file. These and other HTML strings are written to the output file when
CXFisCalDlg::OnCreateCalendar() is called (when the user clicks on the Create Calendar button). Additional HTML is written in the functions WriteMonth() and WriteDays().
Here is one of the HTML blocks:
TCHAR *html_start[] =
{
_T("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN")
_T("\" \"http://www.w3.org/TR/html4/loose.dtd\">\n\n"),
_T("<html>\n"),
_T("INSERT_PARAMS_HERE"),
_T("<head>\n"),
_T("<link rel=\"stylesheet\" type=\"text/css\" href=\"")
CSS_FILE
_T("\">\n"),
_T("<title>Fiscal Year INSERT_FISCAL_YEAR_HERE</title>\n"),
_T("</head>\n\n"),
_T("<body>\n\n"),
_T("<div style=\"margin-left: 5px; margin-right: 5px\">\n\n"),
_T("<table width=\"100%\" summary=\"Fiscal year\">\n"),
_T("<tr><td class=\"year_header\" style=\"color: INSERT_YEAR_COLOR_HERE")
_T("\">INSERT_FISCAL_YEAR_HERE</td></tr>\n"),
_T("</table>\n\n"),
_T("<table width=\"100%\" style=\"border-collapse: collapse\" ")
_T("title=\"Fiscal Year INSERT_FISCAL_YEAR_HERE\" summary=\"Fiscal calendar\">\n"),
NULL
};
As this block is being written to the output file, the INSERT_xxxxx_HERE strings
are replaced with current values.
How To Use
To integrate XDate into your own program, you first need to add XDate.h to your project.
If you want to use the CFiscalDate Trace facility, also include XTrace.h in your project directory.
Next, include XDate.h in the module where you want to use the XDate classes.
For more details on how to use, please see XDateTestDlg.cpp.
CFiscalDate Class Members
| Construction | ||
| CFiscalDate() | Default constructor | |
| CFiscalDate(int month_start, int day_start, eFiscalWeekOne ew, int week_start) | Construction from basic fiscal year settings | |
| CFiscalDate(int month_start, int day_start, eFiscalWeekOne ew, int week_start, int fq, int fw, int fy) | Construction from fiscal quarter, week, and year | |
| CFiscalDate(const CFiscalDate& fd) | Copy constructor | |
| CFiscalDate(const CGregorianDate& gd) | Construction from a CGregorianDate | |
| CFiscalDate(time_t t) | C runtime; seconds since 1 Jan 1970 | |
| CFiscalDate(const SYSTEMTIME& SystemTime) | System SYSTEMTIME date | |
Assignment |
||
| CFiscalDate& operator=(const CFiscalDate& id) | CFiscalDate object | |
| CFiscalDate& operator=(const CGregorianDate& gd) | CGregorianDate object | |
| CFiscalDate& operator=(const time_t& t) | C runtime; seconds since 1 Jan 1970 | |
| CFiscalDate& operator=(const SYSTEMTIME& SystemTime) | System SYSTEMTIME date | |
Attributes |
||
| int GetCentury() | Returns century; eg, returns 19 for 1985. | |
| static CFiscalDate GetCurrentTime() | Returns a CFiscalDate object that represents the current time. | |
| CGregorianDate GetFiscalYearEnd(CGregorianDate& year_start) | Returns CGregorianDate object that represents the last day of the fiscal year. | CGregorianDate GetFiscalYearStart(CGregorianDate& year_start) | Returns CGregorianDate object that represents the first day of the fiscal year. |
| bool GetGregorian(int& m, int& d, int& y) const | Returns the current date in mdy. Returns true if date is valid. | |
| int GetQuarter() const | Returns the quarter (1..4) of the current date. | |
| bool GetQuarterStart(int quarter, int& m, int& d, int& y) | Returns the quarter start date in mdy. Returns true if date is valid. | |
| bool GetSystemTime(SYSTEMTIME& SystemTime) const | Returns SYSTEMTIME value for current date. | |
| int GetWeekOfQuarter() const | Returns the week number (1..13) in quarter for current date. | |
| int GetWeekOfYear() const | Returns the week number (1..52) in year for current date. | |
| bool GetWeekStart(int quarter, int week_of_quarter, int& m, int& d, int& y) | Returns week start date for quarter + week_of_quarter. | |
| int GetYear() const | Returns current fiscal year. | |
| int GetYearWithoutCentury() const | Returns year without century; eg, returns 85 for 1985. | |
| static bool IsValidDate(int q, int w, int y) | Returns true if qwy is a valid date, false if not. | |
| bool IsValidDate() const | Returns true if current date is a valid date, false if not. | |
| bool Set(int q, int w, int y) | Sets the current quarter, week, and year. Returns true if date is valid | |
| void SetFiscalYearStart(int m, int d, int y) | Set fiscal year start from mdy. | |
| bool SetFromGregorian(int m, int d, int y) | Sets the date from mdy. Returns true if date is valid. | |
| bool SetFromSystemTime(const SYSTEMTIME& SystemTime) | Sets the current date to the date represented by the SYSTEMTIME SystemTime. Returns true if date is valid. | |
| bool SetFromSystemTime() | Sets the current date to the date returned by the system function GetLocalTime(). Returns true if date is valid. | |
| void SetQuarter(int q) | Set current quarter to q. | |
| void SetWeek(int w) | Set current week to w. | |
| void SetYear(int y) | Set current year to y. | |
Logical Operators |
||
| bool operator==(const CFiscalDate& rhs) const | Returns true if dates are equal. | |
| bool operator!=(const CFiscalDate& rhs) const | Returns true if dates are not equal. | |
| bool operator<(const CFiscalDate& rhs) const | Returns true if lhs is less than rhs. | |
| bool operator>(const CFiscalDate& rhs) const | Returns true if lhs is greater than rhs. | |
| bool operator<=(const CFiscalDate& rhs) const | Returns true if lhs is less than or equal to rhs. | |
| bool operator>=(const CFiscalDate& rhs) const | Returns true if lhs is greater than or equal to rhs | |
Math Operators |
||
| CFiscalDate& operator+(int n) | Add n weeks to current date. | |
| CFiscalDate& operator-(int n) | Subtract n weeks from current date. | |
| CFiscalDate& operator+=(int n) | Add n weeks to current date. | |
| CFiscalDate& operator-=(int n) | Subtract n weeks from current date. | |
| CFiscalDate& operator++() | Add one week to current date (prefix). | |
| CFiscalDate& operator--() | Subtract one week from current date (prefix). | |
| CFiscalDate& operator++(int) | Add one week to current date (postfix). | |
| CFiscalDate& operator--(int) | Subtract one week from current date (postfix). | |
Operations |
||
| bool AddQuarters(int n) | Add n quarters to current date (n can be negative to subtract). Returns true if resulting date is valid. | |
| bool AddWeeks(int n) | Add n weeks to current date (n can be negative to subtract). Returns true if resulting date is valid. | |
| bool AddYears(int n) | Add n years to current date (n can be negative to subtract). Returns true if resulting date is valid. | |
Dump/Trace |
||
| virtual void AssertValid() const | Virtual function. By default returns true if current date is valid. | |
| virtual void Dump() const | Virtual function. By default outputs the current date using OutputDebugString(). | |
| virtual void Trace(LPCTSTR lpszMsg = NULL) const | Virtual function. By default outputs an optional message and the current date using OutputDebugString(). | |
References
- Wikipedia has some background on fiscal years here.
Revision History
Version 1.0
- Initial release
Buy latest version
| Buy XDate 1.0 license – $30.00 per developer. Includes full source code to XDateCalc.exe, XFisCal.exe, and XDateTest.exe. |