/*--------------------------------------------------------------
* gtime_adt.h : header file for timestamp related ADTs.
*
* Change Log :
* 6-05-1996 Initial version, Liujian Qian
* $Id: gadt_time.h,v 1.6 1999/01/27 20:59:56 qian Exp $
*-------------------------------------------------------------*/
#ifndef _GTIME_H_
#define _GTIME_H_
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include "gadt.h"
#include "greg_tbls.h" //for translation tables
class GSpan; //forward declarations
class GTimestamp;
//
// Gregorian calendar standards and routines.
// For reference, see [C. Dyreson & R. Snodgrass, "The MultiCal Project"]
//
#define g_max_year (9999999999ll)
#define g_max_month (12)
#define g_century_of(x) ((x) / 100)
#define g_year_of_century(x) ((x) %100)
#define g_year_of_decade(x) (x % 10)
#define g_decade(x) (g_year_of_century(x) / 10)
#define LEAP400 97 //97 leap days in every 400 years
#define SECONDS_IN_MINUTE 60
#define SECONDS_IN_HOUR 3600
#define SECONDS_IN_DAY 86400
#define SECONDS_IN_WEEK 86400*7
#define SECONDS_IN_YEAR 86400*365
#define SECONDS_IN_LEAP_YEAR 86400*366
#define LEAPDAYS_UPTO_1970 477
#define YEARS_IN_GREG 400
#define DAYS_IN_GREG 146097
#define SECONDS_IN_GREG 0x2f0605980ull
#define SECONDS_TO_1970 0xe7791f700ull
#define century_year(x) (x % 100 == 0)
#define year_div_by_400(x) (x % 400 == 0)
#define IS_LEAP_YEAR(x) ((x % 4 == 0) && \
((x % 400 == 0) || (!(x % 100 == 0))))
/**
* unit of a time label/stamp
*/
enum TimeUnit
{
_INVALID =-1,
_SECOND =0,
_MINUTE =1,
_HOUR =2,
_DAY =3,
_WEEK =4,
_YEAR =5,
_MONTH =6,
_SEASON =7,
_DECADE =8,
_CENTURY =9,
_KYEAR =10, //thousand years
_MYEAR =11 //million years
};
/**
*/
enum Months
{
_BAD = -1,
_JAN = 0, _FEB = 1, _MAR = 2, _APR = 3,
_MAY = 4, _JUN = 5, _JUL = 6, _AUG = 7,
_SEP = 8, _OCT = 9, _NOV = 10, _DEC = 11
};
/**
* Gregorian date/time structure. The value
* for the field 'month' and 'day' begin with 1; the rest
* all begin with 0. For example, the following code generates
* a GDate object for Dec 1, 1981:
* GDate d(1981, 12, 1);
*/
struct GDate {
int64 year;
Months month;
short day;
short hour;
short minute;
short second;
static char* month_names[13];
static uint8 days_in_mon[13];
GDate()
{
year = day = hour = minute = second = 0;
month = _JAN;
}
GDate(int64 y, int m, int d, int h=0, int mi=0, int s=0) :
year(y), month( (Months)m), day(d), hour(h), minute(mi), second(s)
{};
Months nameToMonth(const char* mon);
};
//types of timestamps
#define TS_REGULAR 8 //0100
#define TS_SPECIAL 12 //1100
#define TS_SPAN 2 //0010: fixed span
#define TS_VSPAN 15 //1111: variable span
/**
GFC's timestamp class.
GTimestamp is based on the work by MultiCal project of U.
Arizona.
GLOSSARY
<pre>
CHRONON: Unit of time measuring as adopted by a clock. A second
for our purpose. (Would geographical features be
measured to a microsecond??)
TIMESTAMP: A paticular time in the history. Defined by the
number of chronons from the origin.
SPAN: A period of time. A FIXED span is just a count of
chronons; while a VARIABLE span (line a 'month')
may have a duration that depends on a paticular calendar.
ORIGIN: We specify "Midnight January 1, 1970 GMT" as the origin for
timestamps (same as the unix time origin.) This is merely
a reference point. The actual timestamp represented can
cover the whole history of the Earth, using just 64 bits.
</pre>
TIMESTAMP FORMAT:
We use a 64 bit integer to represent the timestamp.
The bits pattern is as below:
<pre>
63 0
xxxx,x,xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
| | |
| | seconds from the ORIGIN (59 bits; good for 36 billion years)
| sign (1:after ORIGIN, 0: before ORIGIN)
type (see below)
Type:
1100: for special timestamps ("beginning", "forever",and null).
C000000000000001 = beginning (big bang)
C000000000000002 = forever (big crunch?)
C000000000000000 = NULL timestamp.
0100: a regular timestamp.
0010: a fixed span or duration (sign is meaningless here)
1111: a variable span. (to be defined -- L.Q.)
</pre>
*/
class GTimestamp : public GTemporal
{
public:
/**
* timestamp internal representation.
*/
typedef struct tag_time_internal
{
#if defined(i386)
//using byte order on Intel x86 processors.
unsigned secs_lo : 32; // seconds since origin
// word boundary
unsigned secs_hi : 27; // seconds since origin
unsigned sign : 1; // sign flag -- 0 before, 1 after origin
unsigned type : 4; // types
#else
//assumming byte order for Sun Sparc processors.
unsigned type : 4; // types
unsigned sign : 1; // sign flag -- 0 before, 1 after origin
unsigned secs_hi : 27; // seconds since origin
// word boundary
unsigned secs_lo : 32; // seconds since origin
#endif
} timestamp_internal;
/**
* actual storage: 64 bits whatsoever.
*/
union
{
timestamp_internal ts;
int64 val;
}t;
static long _seconds[6];
public:
/**
* constructors
*/
GTimestamp();
/**
*/
GTimestamp(char* special);
/**
*/
GTimestamp(const GDate& d);
/**
*/
GTimestamp(int year);
/**
*/
GTimestamp(int year, int mon, int day);
/**
*/
GTimestamp(int year, int mon, int day, int hour, int minute, int sec);
/**
*/
GTimestamp(const GTimestamp& copy);
virtual GTimestamp& operator= (const GTimestamp& other);
virtual GType type (void) const {return _Timestamp; }
virtual Result init (void) ;
virtual uint32 getPSize() const;
/**
*translate a GMT user time gregorian date into a timestamp.
*The user format must be exact as "Oct 09 12:23:45 1996"
*/
virtual Result input (const char* in);
/**
*translates a timestamp into GMT user format, with the form of
*"Oct 09 12:23:45 GMT 1996".
*To translate GMT time into local time, use system library functions.
*/
virtual Result output (char*& out);
/** same as output; except in a terse format according to the
* unit of the timestamp.
*/
Result output (char*& out, TimeUnit u );
virtual Result pack (DataPipe& p);
virtual Result unpack (DataPipe& p);
virtual int cmp(const GADT& a) const;
virtual GADT* clone () const {return new GTimestamp;}
//comparison methods
int cmp(const GTimestamp& other) const;
/**
* change the temporal scale of this value
*/
virtual Result scale (int) ;
/**
* check if this temporal value is Earlier Than 'a'
*/
virtual int before (const GTemporal& a) const;
/**
* check if this temporal value is Later than 'a'
*/
virtual int after (const GTemporal& a) const;
/**
* check if this temporal value is during 'a'
*/
virtual int during (const GTemporal& a) const;
/**
* check if this temporal value overlaps 'a'
*/
virtual int overlap (const GTemporal& a) const;
/**
*/
bool operator!=(GTimestamp st2) const;
/**
*/
bool operator==(GTimestamp st2) const;
/**
*/
bool operator<(GTimestamp st2) const;
/**
*/
bool operator<=(GTimestamp st2) const;
/**
*/
bool operator>=(GTimestamp st2) const;
/**
*/
bool operator>(GTimestamp st2) const;
/**
* type conversion (timestamp -> int64)
*/
operator int64() const { return (uint64) t.val; }
/**
*/
GTimestamp& operator+=(uint64 seconds);
/**
*/
GTimestamp& operator-=(uint64 seconds);
/**
*/
GTimestamp& operator+=(GTimestamp span);
/**
*/
GTimestamp& operator-=(GTimestamp span);
/**
* convert a gregorian date into timestamp (seconds since origin.)
* Originally written by "MultiCal" group; modified to support hour/min/sec.
*/
Result date2TS (const GDate* date);
/**
* handy versionf of date2TS
*/
void setDate (const GDate& date) {date2TS(&date);};
/**
* Translate from seconds format to explicit Greogrian date.
* Original version by "MultiCal" group; modified to support
* hour/min/sec.
*/
Result date (GDate* date) const;
/**
* Return a time label that is in user format and in accordance to
* the precision. (For example, if the precision is set to year, the
* time label will only includ the year number, such as "1996", instead
* of "JAN 1 00:00:00 1996".)
*/
Result timeLabel(TimeUnit unit, char* str);
/**
* set timestamp to just indicate the year.
*/
void setYear(int year);
/**
* This method turns the timestamp into a special one
* representing beginning of the universe (big bang). This
* timestamp is smaller than any other timestamp.
*/
void setToOrigin();
/**
* This turns the timestamp into a "forever" one,
* which is greater than any other timestamp.
*/
void setToForever();
/**
* This method turn the timestamp into a fixed span.
*/
void setToSpan(int64 span=-1);
//status reporting/setting
friend ostream& operator << (ostream& s, GTimestamp& t);
};
//for proper initialization of timestamp ADT in GFC
static class _GITimestamp{
static int cnt;
public:
_GITimestamp()
{
if(cnt++==0)
GADTManager::registerADT(new GADTDef(_Timestamp,"Timestamp",
1, 0, new GTimestamp));
}
~_GITimestamp()
{
if(--cnt==0)
GADTManager::removeADT(_Timestamp);
}
} gi_timestamp;
//two special timestamps: global.
extern GTimestamp ORIGIN;
extern GTimestamp FOREVER;
#endif
Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999