1176 lines
30 KiB
C++
1176 lines
30 KiB
C++
|
|
/*
|
||
|
|
----
|
||
|
|
This file is part of SECONDO.
|
||
|
|
|
||
|
|
Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
||
|
|
Database Systems for New Applications.
|
||
|
|
|
||
|
|
SECONDO is free software; you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU General Public License as published by
|
||
|
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
SECONDO is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU General Public License
|
||
|
|
along with SECONDO; if not, write to the Free Software
|
||
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
----
|
||
|
|
|
||
|
|
//paragraph [1] Title: [{\Large \bf \begin{center}] [\end{center}}]
|
||
|
|
//paragraph [10] Footnote: [{\footnote{] [}}]
|
||
|
|
//[->] [$\rightarrow$]
|
||
|
|
//[TOC] [\tableofcontents]
|
||
|
|
//[_] [\_]
|
||
|
|
|
||
|
|
[1] Implementation of the Date Algebra
|
||
|
|
|
||
|
|
|
||
|
|
December 11-26, 2002 Zhiming Ding
|
||
|
|
|
||
|
|
December 2005, Victor Almeida deleted the deprecated algebra levels
|
||
|
|
(~executable~, ~descriptive~, and ~hibrid~). Only the executable
|
||
|
|
level remains. Models are also removed from type constructors.
|
||
|
|
|
||
|
|
[TOC]
|
||
|
|
|
||
|
|
|
||
|
|
1 Preliminaries
|
||
|
|
|
||
|
|
This algebra provides one type constructor ~date~, and seven operators:
|
||
|
|
\verb+<+ , = , \verb+>+, ~year[_]of~, ~month[_]of~, ~day[_]of~, and ~thedate~.
|
||
|
|
|
||
|
|
Signatures of these operators are listed below:
|
||
|
|
|
||
|
|
* \verb+<+ , = , \verb+>+
|
||
|
|
|
||
|
|
---- date x date -> bool
|
||
|
|
----
|
||
|
|
compare two dates.
|
||
|
|
|
||
|
|
|
||
|
|
* year[_]of, month[_]of, day[_]of
|
||
|
|
|
||
|
|
---- date -> int
|
||
|
|
----
|
||
|
|
extract year, month, day information from a date.
|
||
|
|
|
||
|
|
|
||
|
|
* thedate
|
||
|
|
|
||
|
|
---- int x int x int -> date
|
||
|
|
----
|
||
|
|
generates a date according to the specified year, month,
|
||
|
|
and day information
|
||
|
|
|
||
|
|
|
||
|
|
The algebra provides basic checks on the validity of a date.
|
||
|
|
For instance, Fabruary in leap years
|
||
|
|
(every 4 years except 100th year, and every 400th year) has
|
||
|
|
29 days, and Fabruary in normal years only
|
||
|
|
has 28 days.
|
||
|
|
|
||
|
|
|
||
|
|
1.1 Includes
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "Attribute.h"
|
||
|
|
|
||
|
|
|
||
|
|
#include "Algebra.h"
|
||
|
|
#include "NestedList.h"
|
||
|
|
#include "QueryProcessor.h"
|
||
|
|
#include "AlgebraManager.h"
|
||
|
|
#include "StandardTypes.h"
|
||
|
|
#include "StringUtils.h"
|
||
|
|
#include "ListUtils.h"
|
||
|
|
#include <iostream>
|
||
|
|
#include <string>
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
using namespace std;
|
||
|
|
extern NestedList* nl;
|
||
|
|
extern QueryProcessor *qp;
|
||
|
|
extern AlgebraManager *am;
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
1.2 Date Validating Function
|
||
|
|
|
||
|
|
This function checks whether an input date is valid. The month
|
||
|
|
and the day must be within valid
|
||
|
|
boundaries. However, the year can be any integer. For instance, -100 represents
|
||
|
|
the year of 100BC.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
bool isdate(int Day, int Month, int Year)
|
||
|
|
{
|
||
|
|
bool res=true;
|
||
|
|
bool leapyear=false;
|
||
|
|
int daysinmonth=0;
|
||
|
|
if (((Year % 4==0) && (Year % 100!=0)) || (Year % 400==0))
|
||
|
|
leapyear=true; else leapyear=false;
|
||
|
|
if ((Month<1)||(Month>12)) res=false;
|
||
|
|
else
|
||
|
|
{
|
||
|
|
switch (Month)
|
||
|
|
{
|
||
|
|
case 1:
|
||
|
|
case 3:
|
||
|
|
case 5:
|
||
|
|
case 7:
|
||
|
|
case 8:
|
||
|
|
case 10:
|
||
|
|
case 12: daysinmonth=31; break;
|
||
|
|
case 4:
|
||
|
|
case 6:
|
||
|
|
case 9:
|
||
|
|
case 11: daysinmonth=30; break;
|
||
|
|
case 2: if (leapyear) daysinmonth=29; else daysinmonth=28;
|
||
|
|
}
|
||
|
|
if ((Day<1)||(Day>daysinmonth)) res=false;
|
||
|
|
}
|
||
|
|
return res;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
2 Type Constructor ~date~
|
||
|
|
|
||
|
|
2.1 Data Structure - Class ~Date~
|
||
|
|
|
||
|
|
In order to use ~date~ as an attribute type in tuple definitions,
|
||
|
|
we must derive the class ~Date~ from ~Attribute~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
class Date: public Attribute
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
Date(bool Defined, int Day, int Month, int Year);
|
||
|
|
Date();
|
||
|
|
~Date();
|
||
|
|
int GetDay() const;
|
||
|
|
int GetMonth() const;
|
||
|
|
int GetYear() const;
|
||
|
|
void SetDay( int Day);
|
||
|
|
void SetMonth( int Yonth);
|
||
|
|
void SetYear( int Year);
|
||
|
|
void Set(bool Defined, int Day, int Month, int Year);
|
||
|
|
/*
|
||
|
|
~readFrom~
|
||
|
|
|
||
|
|
Sets this date value to the given string. accepted formats are
|
||
|
|
yyy-mm-dd and dd.mm.yyyy where leading zeros can be ommitted.
|
||
|
|
If the string does not represent a valid day, this Date value
|
||
|
|
remains unchanged and false is returned.
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool readFrom(string& d);
|
||
|
|
|
||
|
|
/*
|
||
|
|
~ReadFromString~
|
||
|
|
|
||
|
|
works similar to the readFrom function. In contrast to that function,
|
||
|
|
this Date is set to be false in the string does not represent a
|
||
|
|
valid date.
|
||
|
|
|
||
|
|
*/
|
||
|
|
virtual void ReadFromString(string d);
|
||
|
|
/*
|
||
|
|
getCsvStr
|
||
|
|
|
||
|
|
Returns a string represnetation of this date value.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
virtual string getCsvStr() const;
|
||
|
|
|
||
|
|
void successor(const Date *d, Date *s) const;
|
||
|
|
/*************************************************************************
|
||
|
|
|
||
|
|
The following 8 virtual functions: IsDefined(), SetDefined(), HashValue(),
|
||
|
|
CopyFrom(), Compare(), Adjacent(), Clone(), Print(), need to be defined if
|
||
|
|
we want to use ~date~ as an attribute type in tuple definitions.
|
||
|
|
|
||
|
|
*************************************************************************/
|
||
|
|
|
||
|
|
bool IsDefined() const;
|
||
|
|
void SetDefined(bool Defined);
|
||
|
|
size_t Sizeof() const;
|
||
|
|
size_t HashValue() const;
|
||
|
|
void CopyFrom(const Attribute* right);
|
||
|
|
int Compare(const Attribute * arg) const;
|
||
|
|
bool Adjacent(const Attribute * arg) const;
|
||
|
|
Date* Clone() const;
|
||
|
|
ostream& Print( ostream &os ) const;
|
||
|
|
static const string BasicType(){
|
||
|
|
return "date";
|
||
|
|
}
|
||
|
|
static const bool checkType(const ListExpr list){
|
||
|
|
return listutils::isSymbol(list, BasicType());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
private:
|
||
|
|
int day;
|
||
|
|
int month;
|
||
|
|
int year;
|
||
|
|
bool defined;
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
Date::Date(bool Defined, int Day, int Month, int Year)
|
||
|
|
{
|
||
|
|
defined = Defined;
|
||
|
|
day = Day;
|
||
|
|
month = Month;
|
||
|
|
year = Year;
|
||
|
|
}
|
||
|
|
|
||
|
|
Date::Date() {}
|
||
|
|
|
||
|
|
Date::~Date() {}
|
||
|
|
|
||
|
|
int Date::GetDay() const {return day;}
|
||
|
|
|
||
|
|
int Date::GetMonth() const {return month;}
|
||
|
|
|
||
|
|
int Date::GetYear() const {return year;}
|
||
|
|
|
||
|
|
void Date::SetDay(int Day) {day = Day;}
|
||
|
|
|
||
|
|
void Date::SetMonth(int Month) {month = Month;}
|
||
|
|
|
||
|
|
void Date::SetYear(int Year) {year = Year;}
|
||
|
|
|
||
|
|
void Date::Set(bool Defined, int Day, int Month, int Year)
|
||
|
|
{
|
||
|
|
defined = Defined;
|
||
|
|
day = Day;
|
||
|
|
month = Month;
|
||
|
|
year = Year;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Date::readFrom(string& s){
|
||
|
|
|
||
|
|
stringutils::trim(s);
|
||
|
|
|
||
|
|
if(s.length()>99){
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
char *i, *j;
|
||
|
|
int dot = 0;
|
||
|
|
int hyphen = 0;
|
||
|
|
int Year;
|
||
|
|
int Month;
|
||
|
|
int Day;
|
||
|
|
char buf[100];
|
||
|
|
const char* c_string = s.c_str();
|
||
|
|
|
||
|
|
if ( (strcmp(c_string,"-")==0) ) // undefined, special notation
|
||
|
|
{
|
||
|
|
Set(false, 0,0,0);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
//"1998-02-01" or "1999-2-1" or "1.2.1998" or "02.01.1999"
|
||
|
|
strcpy(buf, c_string);
|
||
|
|
int bufLen=strlen(buf);
|
||
|
|
|
||
|
|
|
||
|
|
//basic check on date format
|
||
|
|
for ( i=buf; i<buf+bufLen; i++) {
|
||
|
|
if (*i=='.') dot++;
|
||
|
|
if (*i=='-') hyphen++;
|
||
|
|
if ((*i!='.') && (*i!='-') && ((*i<'0') || (*i>'9'))) {
|
||
|
|
// invalid character
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
if ((hyphen == 2) && (dot == 0)) //format is "1998-02-01"
|
||
|
|
{
|
||
|
|
//extract the year, month, day information from the date
|
||
|
|
i=buf; j=i;
|
||
|
|
while ((*j!='-') && (j<buf+bufLen)) j++;
|
||
|
|
*j=0;
|
||
|
|
Year=atoi(i);
|
||
|
|
|
||
|
|
i=j+1; j=i;
|
||
|
|
while ((*j!='-') && (j<buf+bufLen)) j++;
|
||
|
|
*j=0;
|
||
|
|
Month=atoi(i);
|
||
|
|
|
||
|
|
i=j+1; j=i;
|
||
|
|
while ((*j!='-') && (j<buf+bufLen)) j++;
|
||
|
|
*j=0;
|
||
|
|
Day=atoi(i);
|
||
|
|
} else if ((hyphen == 0) && (dot == 2)) { //format is "1.2.1998"
|
||
|
|
|
||
|
|
//extract the year, month, day information from the date
|
||
|
|
i=buf; j=i;
|
||
|
|
while ((*j!='.') && (j<buf+bufLen)) j++;
|
||
|
|
*j=0;
|
||
|
|
Day=atoi(i);
|
||
|
|
|
||
|
|
i=j+1; j=i;
|
||
|
|
while ((*j!='.') && (j<buf+bufLen)) j++;
|
||
|
|
*j=0;
|
||
|
|
Month=atoi(i);
|
||
|
|
|
||
|
|
i=j+1; j=i;
|
||
|
|
while ((*j!='.') && (j<buf+bufLen)) j++;
|
||
|
|
*j=0;
|
||
|
|
Year=atoi(i);
|
||
|
|
} else {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isdate(Day, Month, Year)) {
|
||
|
|
Set(true, Day, Month, Year);
|
||
|
|
return true;
|
||
|
|
} else {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Date::ReadFromString(string s){
|
||
|
|
if(!readFrom(s)){
|
||
|
|
SetDefined(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
string Date::getCsvStr() const{
|
||
|
|
stringstream ss;
|
||
|
|
Print(ss);
|
||
|
|
return ss.str();
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
/*************************************************************************
|
||
|
|
|
||
|
|
In the following, we give the definitions of the 9 virtual functions
|
||
|
|
which are needed
|
||
|
|
if we want to use ~date~ as an attribute type in tuple definitions.
|
||
|
|
|
||
|
|
*************************************************************************/
|
||
|
|
|
||
|
|
bool Date::IsDefined() const {return (defined); }
|
||
|
|
|
||
|
|
void Date::SetDefined(bool Defined) {defined = Defined; }
|
||
|
|
|
||
|
|
size_t Date::Sizeof() const
|
||
|
|
{
|
||
|
|
return sizeof( *this );
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t Date::HashValue() const
|
||
|
|
{
|
||
|
|
if(!defined) return (0);
|
||
|
|
unsigned long h;
|
||
|
|
h=5*(5*day+month)+year;
|
||
|
|
return size_t(h);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Date::CopyFrom(const Attribute* right)
|
||
|
|
{
|
||
|
|
const Date * d = (const Date*)right;
|
||
|
|
defined = d->defined;
|
||
|
|
day = d->day;
|
||
|
|
month = d->month;
|
||
|
|
year = d->year;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
The function Compare() defines a total order on the data type ~date~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
int Date::Compare(const Attribute * arg) const
|
||
|
|
{
|
||
|
|
int res=0;
|
||
|
|
const Date * d = (const Date* )(arg);
|
||
|
|
if ( !d ) return (-2);
|
||
|
|
|
||
|
|
if (!IsDefined() && !(arg->IsDefined())) res=0;
|
||
|
|
else if (!IsDefined()) res=-1;
|
||
|
|
else if (!(arg->IsDefined())) res=1;
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if ((this->GetYear()) > (d->GetYear())) res=1;
|
||
|
|
else if ((this->GetYear()) < (d->GetYear())) res=-1;
|
||
|
|
else
|
||
|
|
if ((this->GetMonth())>(d->GetMonth())) res=1;
|
||
|
|
else if ((this->GetMonth())<(d->GetMonth())) res=-1;
|
||
|
|
else
|
||
|
|
if ((this->GetDay())>(d->GetDay())) res=1;
|
||
|
|
else if ((this->GetDay())<(d->GetDay())) res=-1;
|
||
|
|
else res=0;
|
||
|
|
}
|
||
|
|
return (res);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Date::successor(const Date *d, Date *s) const
|
||
|
|
{
|
||
|
|
assert(isdate(d->GetDay(), d->GetMonth(), d->GetYear()));
|
||
|
|
|
||
|
|
int Year, Month, Day;
|
||
|
|
Year=d->GetYear(); Month=d->GetMonth(); Day=d->GetDay();
|
||
|
|
// cout<<"OldDate"<<Year<<":"<<Month<<":"<<Day<<endl;
|
||
|
|
bool leapyear=false;
|
||
|
|
int daysinmonth=0;
|
||
|
|
if (((Year % 4==0) && (Year % 100!=0)) || (Year % 400==0))
|
||
|
|
leapyear=true;
|
||
|
|
else leapyear=false;
|
||
|
|
|
||
|
|
switch (Month)
|
||
|
|
{
|
||
|
|
case 1:
|
||
|
|
case 3:
|
||
|
|
case 5:
|
||
|
|
case 7:
|
||
|
|
case 8:
|
||
|
|
case 10:
|
||
|
|
case 12: daysinmonth=31; break;
|
||
|
|
case 4:
|
||
|
|
case 6:
|
||
|
|
case 9:
|
||
|
|
case 11: daysinmonth=30; break;
|
||
|
|
case 2: if (leapyear) daysinmonth=29; else daysinmonth=28;
|
||
|
|
}
|
||
|
|
if ((Day<daysinmonth))
|
||
|
|
Day++;
|
||
|
|
else //==
|
||
|
|
{
|
||
|
|
Day=1;
|
||
|
|
if (Month<12) Month++;
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Month=1;
|
||
|
|
Year++;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
s->year=Year; s->month=Month; s->day=Day; s->defined=true;
|
||
|
|
// cout<<"NewDate"<<Year<<":"<<Month<<":"<<Day<<endl;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool Date::Adjacent(const Attribute *arg) const
|
||
|
|
{
|
||
|
|
const Date *d = (const Date *)arg;
|
||
|
|
if( this->Compare( d ) == 0 ) return 1; //both undefined or they are equal
|
||
|
|
|
||
|
|
if (!IsDefined() || !(arg->IsDefined()))
|
||
|
|
//one is undefined and another defined
|
||
|
|
return 0;
|
||
|
|
else //both defined and they are not equal
|
||
|
|
{
|
||
|
|
Date * auxdate=new Date();
|
||
|
|
|
||
|
|
successor(this, auxdate);
|
||
|
|
if (auxdate->Compare(d)==0)
|
||
|
|
{
|
||
|
|
delete auxdate;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
|
||
|
|
successor(d, auxdate);
|
||
|
|
if (this->Compare(auxdate)==0)
|
||
|
|
{
|
||
|
|
delete auxdate;
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
delete auxdate;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Date* Date::Clone() const
|
||
|
|
{
|
||
|
|
return (new Date( *this));
|
||
|
|
}
|
||
|
|
|
||
|
|
ostream& Date::Print(ostream &os) const
|
||
|
|
{ if(!IsDefined()) return os << "undef";
|
||
|
|
return (os << day << "." << month << "." << year);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
2.2 List Representation
|
||
|
|
|
||
|
|
The list representation of a date is
|
||
|
|
|
||
|
|
---- (isdefined dd mm yy)
|
||
|
|
----
|
||
|
|
|
||
|
|
2.3 ~In~ and ~Out~ Functions
|
||
|
|
|
||
|
|
*/
|
||
|
|
ListExpr
|
||
|
|
OutDate( ListExpr typeInfo, Word value )
|
||
|
|
{
|
||
|
|
Date* date;
|
||
|
|
string outputStr;
|
||
|
|
char buf[100];
|
||
|
|
|
||
|
|
date = (Date*)(value.addr);
|
||
|
|
if (date->IsDefined())
|
||
|
|
{
|
||
|
|
sprintf(buf, "%02d.%02d.%d", date->GetDay(),
|
||
|
|
date->GetMonth(), date->GetYear()); //eg. "01.02.1993"
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
strcpy(buf,"-");
|
||
|
|
}
|
||
|
|
outputStr = buf;
|
||
|
|
return (nl->StringAtom(outputStr));
|
||
|
|
}
|
||
|
|
|
||
|
|
Word
|
||
|
|
InDate( const ListExpr typeInfo, const ListExpr instance,
|
||
|
|
const int errorPos, ListExpr& errorInfo, bool& correct )
|
||
|
|
{
|
||
|
|
if (listutils::isSymbolUndefined(instance)) {
|
||
|
|
Date* date = new Date(false,0,0,0);
|
||
|
|
correct = true;
|
||
|
|
return SetWord(date);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nl->AtomType(instance)!=StringType){
|
||
|
|
correct = false;
|
||
|
|
return SetWord(Address(0));
|
||
|
|
}
|
||
|
|
Date* date = new Date(false,0,0,0);
|
||
|
|
string s = nl->StringValue(instance);
|
||
|
|
if(!date->readFrom(s)){
|
||
|
|
delete date;
|
||
|
|
correct = false;
|
||
|
|
return SetWord(Address(0));
|
||
|
|
}
|
||
|
|
correct = true;
|
||
|
|
return SetWord(date);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
/***********************************************************************
|
||
|
|
|
||
|
|
The following 5 functions must be defined if we want to use ~date~ as
|
||
|
|
an attribute type in tuple definitions.
|
||
|
|
|
||
|
|
************************************************************************/
|
||
|
|
|
||
|
|
Word
|
||
|
|
CreateDate( const ListExpr typeInfo )
|
||
|
|
{
|
||
|
|
return (SetWord( new Date( false, 0, 0, 0 )));
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
DeleteDate( const ListExpr typeInfo, Word& w )
|
||
|
|
{
|
||
|
|
delete (Date*) w.addr;
|
||
|
|
w.addr = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
void
|
||
|
|
CloseDate( const ListExpr typeInfo, Word& w )
|
||
|
|
{
|
||
|
|
delete (Date*) w.addr;
|
||
|
|
w.addr = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
Word
|
||
|
|
CloneDate( const ListExpr typeInfo, const Word& w )
|
||
|
|
{
|
||
|
|
return SetWord( ((Date *)w.addr)->Clone() );
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
SizeOfDate()
|
||
|
|
{
|
||
|
|
return sizeof(Date);
|
||
|
|
}
|
||
|
|
|
||
|
|
void*
|
||
|
|
CastDate( void* addr )
|
||
|
|
{
|
||
|
|
return (new (addr) Date);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
2.4 Function Describing the Signature of the Type Constructor
|
||
|
|
|
||
|
|
This one works for type constructor ~date~ , which is an ``atomic'' type.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr
|
||
|
|
DateProperty()
|
||
|
|
{
|
||
|
|
ListExpr listreplist = nl->TextAtom();
|
||
|
|
ListExpr examplelist = nl->TextAtom();
|
||
|
|
nl->AppendText(listreplist,
|
||
|
|
"Either \"<day>.<month>.<year>\" or \"<year>-<month>-<day>\"");
|
||
|
|
nl->AppendText(examplelist,
|
||
|
|
"\"9.5.1955\" or \"09.05.1955\" or \"1955-5-9\" or \"1955-05-09\"");
|
||
|
|
|
||
|
|
return (nl->TwoElemList(
|
||
|
|
nl->FourElemList(nl->StringAtom("Signature"),
|
||
|
|
nl->StringAtom("Example Type List"),
|
||
|
|
nl->StringAtom("List Rep"),
|
||
|
|
nl->StringAtom("Example List")),
|
||
|
|
nl->FourElemList(nl->StringAtom("-> DATA"),
|
||
|
|
nl->StringAtom(Date::BasicType()),
|
||
|
|
listreplist,
|
||
|
|
examplelist)));
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
2.5 Kind Checking Function
|
||
|
|
|
||
|
|
This function checks whether the type constructor is applied correctly. Since
|
||
|
|
the type constructor ~date~ does not have arguments, this is trivial.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
bool
|
||
|
|
CheckDate( ListExpr type, ListExpr& errorInfo )
|
||
|
|
{
|
||
|
|
return (nl->IsEqual(type, Date::BasicType() ));
|
||
|
|
}
|
||
|
|
/*
|
||
|
|
|
||
|
|
2.6 Creation of the Type Constructor Instance
|
||
|
|
|
||
|
|
*/
|
||
|
|
TypeConstructor date(
|
||
|
|
Date::BasicType(), //name
|
||
|
|
DateProperty, //property function describing signature
|
||
|
|
OutDate, InDate, //Out and In functions
|
||
|
|
0, 0, //SaveToList and RestoreFromList functions
|
||
|
|
CreateDate, DeleteDate, //object creation and deletion
|
||
|
|
0, 0, CloseDate, CloneDate, //object open, save, close, and clone
|
||
|
|
CastDate, //cast function
|
||
|
|
SizeOfDate, //sizeof function
|
||
|
|
CheckDate ); //kind checking function
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
3 Creating Operators
|
||
|
|
|
||
|
|
3.1 Type Mapping Function
|
||
|
|
|
||
|
|
Checks whether the correct argument types are supplied for an operator; if so,
|
||
|
|
returns a list expression for the result type, otherwise the symbol
|
||
|
|
~typeerror~.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
ListExpr
|
||
|
|
DateInt( ListExpr args )
|
||
|
|
{
|
||
|
|
ListExpr arg1;
|
||
|
|
if ( nl->ListLength(args) == 1 )
|
||
|
|
{
|
||
|
|
arg1 = nl->First(args);
|
||
|
|
if ( nl->IsEqual(arg1, Date::BasicType()))
|
||
|
|
return nl->SymbolAtom(CcInt::BasicType());
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
ListExpr
|
||
|
|
DateDateBool( ListExpr args )
|
||
|
|
{
|
||
|
|
ListExpr arg1, arg2;
|
||
|
|
if ( nl->ListLength(args) == 2 )
|
||
|
|
{
|
||
|
|
arg1 = nl->First(args);
|
||
|
|
arg2 = nl->Second(args);
|
||
|
|
if ( nl->IsEqual(arg1, Date::BasicType()) &&
|
||
|
|
nl->IsEqual(arg2, Date::BasicType()) )
|
||
|
|
return nl->SymbolAtom(CcBool::BasicType());
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
ListExpr
|
||
|
|
IntIntIntDate( ListExpr args )
|
||
|
|
{
|
||
|
|
ListExpr arg1, arg2, arg3;
|
||
|
|
if ( nl->ListLength(args) == 3 )
|
||
|
|
{
|
||
|
|
arg1 = nl->First(args);
|
||
|
|
arg2 = nl->Second(args);
|
||
|
|
arg3 = nl->Third(args);
|
||
|
|
if ( nl->IsEqual(arg1, CcInt::BasicType()) &&
|
||
|
|
nl->IsEqual(arg2, CcInt::BasicType()) &&
|
||
|
|
nl->IsEqual(arg3, CcInt::BasicType()))
|
||
|
|
return nl->SymbolAtom(Date::BasicType());
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom(Symbol::TYPEERROR());
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
ListExpr str2dateTM(ListExpr args){
|
||
|
|
string err = " string expected";
|
||
|
|
if(nl->ListLength(args)!=1){
|
||
|
|
return listutils::typeError(err);
|
||
|
|
}
|
||
|
|
ListExpr arg1 = nl->First(args);
|
||
|
|
if(!listutils::isSymbol(arg1,CcString::BasicType())){
|
||
|
|
return listutils::typeError(err);
|
||
|
|
}
|
||
|
|
return nl->SymbolAtom(Date::BasicType());
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
3.3 Value Mapping Functions
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
int
|
||
|
|
dayFun (Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
Date* d;
|
||
|
|
d = ((Date*)args[0].addr);
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
int res=d->GetDay();
|
||
|
|
|
||
|
|
if (d->IsDefined())
|
||
|
|
((CcInt*)result.addr)->Set(true, res);
|
||
|
|
else ((CcInt*)result.addr)->Set(false, res);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
monthFun (Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
Date* d;
|
||
|
|
d = ((Date*)args[0].addr);
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
int res=d->GetMonth();
|
||
|
|
|
||
|
|
if (d->IsDefined())
|
||
|
|
((CcInt*)result.addr)->Set(true, res);
|
||
|
|
else ((CcInt*)result.addr)->Set(false, res);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
yearFun (Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
Date* d;
|
||
|
|
d = ((Date*)args[0].addr);
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
int res=d->GetYear();
|
||
|
|
|
||
|
|
if (d->IsDefined())
|
||
|
|
((CcInt*)result.addr)->Set(true, res);
|
||
|
|
else ((CcInt*)result.addr)->Set(false, res);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
earlierFun (Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
Date* d1;
|
||
|
|
Date* d2;
|
||
|
|
d1 = ((Date*)args[0].addr);
|
||
|
|
d2 = ((Date*)args[1].addr);
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
bool res;
|
||
|
|
|
||
|
|
if (!(d1->IsDefined()) && !(d2->IsDefined())) res=false;
|
||
|
|
else if (!(d1->IsDefined()) && (d2->IsDefined())) res=true;
|
||
|
|
else if ((d1->IsDefined()) && !(d2->IsDefined())) res=false;
|
||
|
|
else
|
||
|
|
{ if ((d1->GetYear()) > (d2->GetYear())) res=false;
|
||
|
|
else if ((d1->GetYear()) < (d2->GetYear())) res=true;
|
||
|
|
else
|
||
|
|
if ((d1->GetMonth())>(d2->GetMonth())) res=false;
|
||
|
|
else if ((d1->GetMonth())<(d2->GetMonth())) res=true;
|
||
|
|
else
|
||
|
|
if ((d1->GetDay())>=(d2->GetDay()))
|
||
|
|
res=false;
|
||
|
|
else res=true;
|
||
|
|
}
|
||
|
|
|
||
|
|
((CcBool*)result.addr)->Set(true, res);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
equalFun (Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
Date* d1;
|
||
|
|
Date* d2;
|
||
|
|
d1 = ((Date*)args[0].addr);
|
||
|
|
d2 = ((Date*)args[1].addr);
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
bool res;
|
||
|
|
|
||
|
|
if (!(d1->IsDefined()) && !(d2->IsDefined())) res=true;
|
||
|
|
else if ((d1->IsDefined()) && (d2->IsDefined()) &&
|
||
|
|
(d1->GetYear() == d2->GetYear()) &&
|
||
|
|
(d1->GetMonth()== d2->GetMonth()) &&
|
||
|
|
(d1->GetDay() == d2->GetDay()))
|
||
|
|
res=true;
|
||
|
|
else res=false;
|
||
|
|
|
||
|
|
((CcBool*)result.addr)->Set(true, res);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
laterFun (Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
Date* d1;
|
||
|
|
Date* d2;
|
||
|
|
d1 = ((Date*)args[0].addr);
|
||
|
|
d2 = ((Date*)args[1].addr);
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
bool res;
|
||
|
|
|
||
|
|
if (!(d1->IsDefined()) && !(d2->IsDefined())) res=false;
|
||
|
|
else if (!(d1->IsDefined()) && (d2->IsDefined())) res=false;
|
||
|
|
else if ((d1->IsDefined()) && !(d2->IsDefined())) res=true;
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if ((d1->GetYear()) > (d2->GetYear())) res=true;
|
||
|
|
else if ((d1->GetYear()) < (d2->GetYear())) res=false;
|
||
|
|
else
|
||
|
|
if ((d1->GetMonth())>(d2->GetMonth())) res=true;
|
||
|
|
else if ((d1->GetMonth())<(d2->GetMonth())) res=false;
|
||
|
|
else
|
||
|
|
if ((d1->GetDay())<=(d2->GetDay()))
|
||
|
|
res=false;
|
||
|
|
else res=true;
|
||
|
|
}
|
||
|
|
|
||
|
|
((CcBool*)result.addr)->Set(true, res);
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
int
|
||
|
|
dateFun (Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
CcInt *dd;
|
||
|
|
CcInt *mm;
|
||
|
|
CcInt *yy;
|
||
|
|
dd = (CcInt *)args[0].addr;
|
||
|
|
mm = (CcInt *)args[1].addr;
|
||
|
|
yy = (CcInt *)args[2].addr;
|
||
|
|
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
|
||
|
|
int Day=dd->GetIntval();
|
||
|
|
int Month=mm->GetIntval();
|
||
|
|
int Year=yy->GetIntval();
|
||
|
|
//bool leapyear;
|
||
|
|
//int daysinmonth;
|
||
|
|
Date* res = (Date*) result.addr;
|
||
|
|
if (isdate(Day, Month, Year)) {
|
||
|
|
res->Set(true, Day, Month, Year);
|
||
|
|
} else {
|
||
|
|
res->Set(false, 0, 0, 0);
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
int
|
||
|
|
str2dateFun (Word* args, Word& result, int message, Word& local, Supplier s)
|
||
|
|
{
|
||
|
|
result = qp->ResultStorage(s);
|
||
|
|
Date* res = static_cast<Date*>(result.addr);
|
||
|
|
CcString* str = static_cast<CcString*>(args[0].addr);
|
||
|
|
if(!str->IsDefined()){
|
||
|
|
res->SetDefined(false);
|
||
|
|
} else {
|
||
|
|
string st = str->GetValue();
|
||
|
|
res->ReadFromString(st);
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
3.4 Definition of Operators
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
const string DaySpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
||
|
|
"\"Example\" )"
|
||
|
|
"( <text>(date) -> int</text--->"
|
||
|
|
"<text>day_of ( _ )</text--->"
|
||
|
|
"<text>extract the day info. from a date."
|
||
|
|
"</text--->"
|
||
|
|
"<text>query day_of ( date1 )</text--->"
|
||
|
|
") )";
|
||
|
|
|
||
|
|
const string MonthSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
||
|
|
"\"Example\" )"
|
||
|
|
"( <text>(date) -> int</text--->"
|
||
|
|
"<text>month_of ( _ )</text--->"
|
||
|
|
"<text>extract the month info. from a date."
|
||
|
|
"</text--->"
|
||
|
|
"<text>query month_of ( date1 )</text--->"
|
||
|
|
") )";
|
||
|
|
|
||
|
|
const string YearSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
||
|
|
"\"Example\" )"
|
||
|
|
"( <text>(date) -> int</text--->"
|
||
|
|
"<text>year_of ( _ )</text--->"
|
||
|
|
"<text>extract the year info. from a date."
|
||
|
|
"</text--->"
|
||
|
|
"<text>query year_of ( date1 )</text--->"
|
||
|
|
") )";
|
||
|
|
|
||
|
|
const string EarlierSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
||
|
|
"\"Example\" )"
|
||
|
|
"( <text>(date date) -> bool</text--->"
|
||
|
|
" <text>_ < _</text--->"
|
||
|
|
"<text>Earlier predicate.</text--->"
|
||
|
|
"<text>query date1 < date2</text--->"
|
||
|
|
") )";
|
||
|
|
const string EqualSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
||
|
|
"\"Example\" )"
|
||
|
|
"( <text>(date date) -> bool</text--->"
|
||
|
|
"<text>_ = _</text--->"
|
||
|
|
"<text>Equal predicate.</text--->"
|
||
|
|
"<text>query date1 = date2</text--->"
|
||
|
|
") )";
|
||
|
|
|
||
|
|
const string LaterSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
||
|
|
"\"Example\" )"
|
||
|
|
"( <text>(date date) -> bool</text--->"
|
||
|
|
"<text>_ > _</text--->"
|
||
|
|
"<text>Later predicate.</text--->"
|
||
|
|
"<text>query date1 > date2</text--->"
|
||
|
|
") )";
|
||
|
|
|
||
|
|
const string DateSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
||
|
|
"\"Example\" )"
|
||
|
|
"( <text>(int int int) -> date</text--->"
|
||
|
|
"<text>thedate ( <day>, <month>, <year> ) where"
|
||
|
|
" <day>, <month> and <year> are of type int"
|
||
|
|
"</text--->"
|
||
|
|
"<text>To generate a date.</text--->"
|
||
|
|
"<text>let date1 = thedate(5,4,2003)</text--->"
|
||
|
|
") )";
|
||
|
|
|
||
|
|
const string str2dateSpec = "( ( \"Signature\" \"Syntax\" \"Meaning\" "
|
||
|
|
"\"Example\" )"
|
||
|
|
"( <text>string -> date</text--->"
|
||
|
|
"<text> str2date(_)"
|
||
|
|
"</text--->"
|
||
|
|
"<text>Converts a string to a date. If the string is undefined "
|
||
|
|
"or is not a valid date, the result will be undefined. "
|
||
|
|
"Allowed formats are dd.mm.yyyy and yyyy-mm-dd where leading zeros "
|
||
|
|
" can be omitted."
|
||
|
|
".</text--->"
|
||
|
|
"<text>query str2date(\"2011-05-23\") = str2date(\"23.5.2011\")</text--->"
|
||
|
|
") )";
|
||
|
|
/*
|
||
|
|
The above strings are used to explain the signature and the
|
||
|
|
meaning of operators.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
Operator day (
|
||
|
|
"day_of", //name
|
||
|
|
DaySpec, //specification
|
||
|
|
dayFun, //value mapping
|
||
|
|
Operator::SimpleSelect, //trivial selection function
|
||
|
|
DateInt //type mapping
|
||
|
|
);
|
||
|
|
|
||
|
|
Operator month (
|
||
|
|
"month_of", //name
|
||
|
|
MonthSpec, //specification
|
||
|
|
monthFun, //value mapping
|
||
|
|
Operator::SimpleSelect, //trivial selection function
|
||
|
|
DateInt //type mapping
|
||
|
|
);
|
||
|
|
|
||
|
|
Operator year (
|
||
|
|
"year_of", //name
|
||
|
|
YearSpec, //specification
|
||
|
|
yearFun, //value mapping
|
||
|
|
Operator::SimpleSelect, //trivial selection function
|
||
|
|
DateInt //type mapping
|
||
|
|
);
|
||
|
|
|
||
|
|
Operator earlier (
|
||
|
|
"<", //name
|
||
|
|
EarlierSpec, //specification
|
||
|
|
earlierFun, //value mapping
|
||
|
|
Operator::SimpleSelect, //trivial selection function
|
||
|
|
DateDateBool //type mapping
|
||
|
|
);
|
||
|
|
|
||
|
|
Operator opequal (
|
||
|
|
"=", //name
|
||
|
|
EqualSpec, //specification
|
||
|
|
equalFun, //value mapping
|
||
|
|
Operator::SimpleSelect, //trivial selection function
|
||
|
|
DateDateBool //type mapping
|
||
|
|
);
|
||
|
|
|
||
|
|
Operator later (
|
||
|
|
">", //name
|
||
|
|
LaterSpec, //specification
|
||
|
|
laterFun, //value mapping
|
||
|
|
Operator::SimpleSelect, //trivial selection function
|
||
|
|
DateDateBool //type mapping
|
||
|
|
);
|
||
|
|
|
||
|
|
Operator thedate (
|
||
|
|
"thedate", //name
|
||
|
|
DateSpec, //specification
|
||
|
|
dateFun, //value mapping
|
||
|
|
Operator::SimpleSelect, //trivial selection function
|
||
|
|
IntIntIntDate //type mapping
|
||
|
|
);
|
||
|
|
|
||
|
|
|
||
|
|
Operator str2date (
|
||
|
|
"str2date", //name
|
||
|
|
str2dateSpec, //specification
|
||
|
|
str2dateFun, //value mapping
|
||
|
|
Operator::SimpleSelect, //trivial selection function
|
||
|
|
str2dateTM //type mapping
|
||
|
|
);
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
4 Creating the Algebra
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
class DateAlgebra : public Algebra
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
DateAlgebra() : Algebra()
|
||
|
|
{
|
||
|
|
AddTypeConstructor( &date );
|
||
|
|
|
||
|
|
date.AssociateKind(Kind::DATA());
|
||
|
|
date.AssociateKind(Kind::CSVIMPORTABLE());
|
||
|
|
date.AssociateKind(Kind::CSVEXPORTABLE());
|
||
|
|
|
||
|
|
AddOperator( &day );
|
||
|
|
AddOperator( &month );
|
||
|
|
AddOperator( &year );
|
||
|
|
AddOperator( &earlier );
|
||
|
|
AddOperator( &opequal);
|
||
|
|
AddOperator( &later );
|
||
|
|
AddOperator( &thedate );
|
||
|
|
AddOperator( &str2date );
|
||
|
|
}
|
||
|
|
~DateAlgebra() {};
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
5 Initialization
|
||
|
|
|
||
|
|
Each algebra module needs an initialization function. The algebra manager
|
||
|
|
has a reference to this function if this algebra is included in the list
|
||
|
|
of required algebras, thus forcing the linker to include this module.
|
||
|
|
|
||
|
|
The algebra manager invokes this function to get a reference to the instance
|
||
|
|
of the algebra class and to provide references to the global nested list
|
||
|
|
container (used to store constructor, type, operator and object information)
|
||
|
|
and to the query processor.
|
||
|
|
|
||
|
|
The function has a C interface to make it possible to load the algebra
|
||
|
|
dynamically at runtime.
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
extern "C"
|
||
|
|
Algebra*
|
||
|
|
InitializeDateAlgebra( NestedList* nlRef,
|
||
|
|
QueryProcessor* qpRef,
|
||
|
|
AlgebraManager* amRef )
|
||
|
|
{
|
||
|
|
nl = nlRef;
|
||
|
|
qp = qpRef;
|
||
|
|
am = amRef;
|
||
|
|
return (new DateAlgebra());
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
|
||
|
|
6 Other work
|
||
|
|
|
||
|
|
6.1 Syntax Specification
|
||
|
|
|
||
|
|
We need to write the following DateAlgebra.spec file to indicate the syntax
|
||
|
|
of the operations in the date algebra:
|
||
|
|
|
||
|
|
---- operator year[_]of alias YEAR[_]OF pattern op ( _ )
|
||
|
|
operator month[_]of alias MONTH[_]OF pattern op ( _ )
|
||
|
|
operator day[_]of alias DAY[_]OF pattern op ( _ )
|
||
|
|
operator thedate alias THEDATE pattern op ( _, _, _ )
|
||
|
|
----
|
||
|
|
|
||
|
|
//[->] [$\rightarrow$]
|
||
|
|
|
||
|
|
6.2 Display Function
|
||
|
|
|
||
|
|
We need to add the following display function into DisplayTTY.h and
|
||
|
|
DisplayTTY.cpp
|
||
|
|
(under the secondo/UserInterface/ subdirectary) to display date correctly:
|
||
|
|
|
||
|
|
---- void
|
||
|
|
DisplayTTY::DisplayDate(ListExpr type,ListExpr numType,ListExpr value)
|
||
|
|
{
|
||
|
|
ListExpr d, m, y;
|
||
|
|
if( nl->IsAtom( value ) &&
|
||
|
|
nl->AtomType( value ) == SymbolType &&
|
||
|
|
nl->SymbolValue( value ) == "undef" )
|
||
|
|
{
|
||
|
|
cout << "UNDEFINED";
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
d = nl->Second( value ) ;
|
||
|
|
m = nl->Third( value ) ;
|
||
|
|
y = nl->Fourth( value );
|
||
|
|
nl->WriteListExpr( d, cout );
|
||
|
|
cout << ",";
|
||
|
|
nl->WriteListExpr( m, cout );
|
||
|
|
cout << ",";
|
||
|
|
nl->WriteListExpr( y, cout );
|
||
|
|
}
|
||
|
|
}
|
||
|
|
----
|
||
|
|
|
||
|
|
*/
|
||
|
|
|