12,446,418 members (52,622 online)
alternative version

46.3K views
19 bookmarked
Posted

Simple(x) Date & Time Math Parser

, 22 Apr 2004 CPOL
 Rate this:
Date and time class from the SimplexParser freeware.

Introduction

In fact, it is not difficult to find a C/C++ date & time class for our main purposes. One of the best is surely P J Naughter's DTime. To bring the functionality for a Date & Time Mathematical Parser, we need additional methods to this or a special class for those purposes. SimplexParser has such a class, so I am decided to set it up to the CodeProject site.

Sample Operations

The parser interprets editor's code like:

`Result = Startdatetime + 40 hours + 12 min + 1 year`

in the form:

```Result = C<[21.04.2004 | 16:19:18] + h[40] + m[12] + Y[1]
Result = 23.04.2005 08:31:18```

or as span:

`Result = 366.925 days or +366d 22h 12m 0s`

or as:

`Julian Date: Result = 2453483.855069`

and so on...

whereby C< stands for Start Clock, D< for Start Date and T< for Start Time. Or:

```Result = Startdate - Enddate
Result = C<[21.04.2004 | 16:19:18] - C>[20.03.2003 | 06:19:15]
Result = +398d 10h 0m 3s```

whereby C> stands for End Clock, D> for End Date and T> for End Time. The syntax was introduced in the early days of development and simplifies the parser's error input check. The output is in the normal form like +366d 22h 12m 0s (day, hour, minute and sec.) or 21.04.2004 16:19:18 or 04/21/2004.

Julian Day Algorithm

The parser's date & time class is based on the Julian Day system. The Julian Day is the number of days since noon on January 1, -4712, i.e., January 1, 4713 BC. It was proposed by J. J. Scaliger in 1583, so the name for this system derived from Julius Scaliger (not Julius Caesar). Scaliger defined Day One as a day when three calendrical cycles converged. The first cycle was the 28 year period over which the Julian calendar repeats days of the week (the so-called solar number). After 28 years, all the dates fall on the same days of the week, so one need only buy 28 calendars. (Note that since the Gregorian calendar was adopted, the calendar now takes 400 years to repeat.) The second was the 19 year golden number cycle over which phases of the moon almost land on the same dates of the year. The third cycle was the 15 year ancient Roman tax cycle of Emperor Constantine (the so-called indiction). Scaliger picked January 1, 4713 BC on the Julian calendar as Day One. The three cycles coincide every 7980 years. For more information, please see: this or this.

CJulianDay class

The following code shows the main methods from the `CJulianDay` class. Some of the method names are well known from other codes:

```//...

class CJulianDay
{
public:
CJulianDay();
virtual ~CJulianDay();

// Member Functions
public:
// Gives Julian Date back
bool Enter(CString& strBaseDate, CString&
strBaseTime, CString strInput, double& dJulian);
double CalcJulianDayTime(CString& strBaseDate,
CString& strBaseTime, CString strInput, bool bSignPlus = true);
double GetJulianDayTime(CString strBaseDate, CString strBaseTime);

CString WeekNumber(int Jul);
CString DayNumber(int Jul);
CString WeekDay(int Jul);

//...

bool IsLeapYear(int nYear);
int DaysInMonth(int nMonth, BOOL bLeapYear);

double HmsToDec(CString strTime);
CString DecToHms(double dDec, bool bF);

protected:
double DatToJul(CString strDate);
CString JulToDat(double Jul);

bool ValidDate(int nYear, int nMonth, int nDay);
bool IsValidDate(CString strDate, int& nDay,
int& nMonth, int& nYear);

double EvaluateNumberOfDays(CString strInput);
int EvaluateNumberOfYears(CString strDate, CString strInput);
int EvaluateNumberOfMonth(CString strDate, CString strInput);
int EvaluateNumberOfWeeks(CString strInput);
};

//...```

Using the code

You can use this code as shown next:

```//...

case IDM_VERNALEQUINOX:
{
double m = ((double) date.GetYear() - 2000.0) / 1000.0;
double ve = 2451623.80984 + 365242.37404 * m +
0.05169 * m * m - 0.00411 * m * m * m -
0.00057 * m * m * m * m ;

CJulianDay Julian;
CString strDate, strTime;
Julian.Enter(strDate, strTime, _T(""), ve);
strResult = strDate + _T(" ") + strTime;

break;
}

//...```

or

```//...

CJulianDay Julian;
result.dJulianDay = Julian.CalcJulianDayTime(m_strBaseDate,
m_strBaseTime, result.Command, true);

//...```

I hope that the code is reasonably obvious how to use, so that we can go to the actual parser class `CDateParser`.

CDateParser class

```//...

typedef struct _tagResultStruct
{
CLTimeSpan tmSpan;
LONG value;
CString SubString;
CString Command;
double dJulianDay;
} stDateParser;

class CDateParser
{
protected:
//Implementation
CString m_strFormula;
CString m_strFunction;
CString m_strErrortext;
double m_dFunctionConstant[ANZFUNKTKONST];
CStringArray m_strStandardFunction;

stDateParser Expression(int& nPosition, CString& strCharacter);
stDateParser Factor(int& nPosition, CString& strCharacter);
double Char_n(int& nPosition, CString& strCharacter);
CString GetNextToken(CString& strSrc, const CString strDelim);

private:
CJulianDay m_Julian;
CString m_strBaseDate;
CString m_strBaseTime;
CString m_strAssociateDate;
CString m_strAssociateTime;

public:
int StripFormula(CString& strFormula);
CString GetFormula();
void SetFormula(CString Formula);
void SetFunctConst(int index, double val);

CDateParser();
virtual ~CDateParser();

//Interface
stDateParser Calculation(CString strFormula,
int& ErrorPosition, CString& Errortext,
BOOL strip = true);
};

//...```

Use this class in the following manner:

```//...

CDateParser DateParser;
stDateParser retValue = DateParser.Calculation(m_strFormulainput,
nErrorPosition, strErrortext);

try
{
if (nErrorPosition == 0)
{
if (strErrortext.IsEmpty())
{
if (m_nSpanSet == 1) // Span
{
int days = retValue.tmSpan.GetTotalDays();
int hours = retValue.tmSpan.GetHours();
int minutes = retValue.tmSpan.GetMinutes();
int seconds = retValue.tmSpan.GetSeconds();

//...

//...```

whereby you can use the other public member functions for clean input, and for example, P J Naughter's DTime class `CLTimeSpan` for getting back days, hours, etc. The demo project shows you that.

Certainly, I know that we can make for the demo project a better dialog for all the possibilities. But, maybe later...

History

• 1.0 (18 April 2004) -Initial release.

Acknowledgement

This would not have been possible without all the authors making their code freely available! So, thanks for that, SimplexParser will be available as freeware for all the time.

Share

 Software Developer (Senior) Germany
Ralf is the programmer of the well-known programs SimplexNumerica and SimplexParser. He's been programming since 1986 since he was at the Fraunhofer Institute for Laser Technology (ILT) in Aachen/Germany. His preferred programming language is Visual C++ with MFC/ATL and GFA Basic. Ralf was born near Gerolstein/Germany. He went to Aachen University where he obtained a Diploma of technical physics. He works as a senior design engineer for a fairly large, international company.

You may also be interested in...

 Pro Pro

 First Prev Next
 Screenshot is wrong ronnyek24-Sep-04 8:56 ronnyek 24-Sep-04 8:56
 Timezone? Stephane Rodriguez.24-Apr-04 3:41 Stephane Rodriguez. 24-Apr-04 3:41
 Re: Timezone? Ralf Wirtz25-Apr-04 20:09 Ralf Wirtz 25-Apr-04 20:09
 Re: Timezone? Stephane Rodriguez.26-Apr-04 8:21 Stephane Rodriguez. 26-Apr-04 8:21
 Last Visit: 31-Dec-99 18:00     Last Update: 24-Aug-16 15:13 Refresh 1