date.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 880 行 · 第 1/2 页
CPP
880 行
/*
*
* Copyright (C) 1994, M. A. Sridhar
*
*
* This software is Copyright M. A. Sridhar, 1994. You are free
* to copy, modify or distribute this software as you see fit,
* and to use it for any purpose, provided this copyright
* notice and the following disclaimer are included with all
* copies.
*
* DISCLAIMER
*
* The author makes no warranties, either expressed or implied,
* with respect to this software, its quality, performance,
* merchantability, or fitness for any particular purpose. This
* software is distributed AS IS. The user of this software
* assumes all risks as to its quality and performance. In no
* event shall the author be liable for any direct, indirect or
* consequential damages, even if the author has been advised
* as to the possibility of such damages.
*
*/
//
// A class representing a particular date. Only dates on or after
// Jan 1, 1901 are permitted.
//
// Author: M. A. Sridhar
// Date: November 9th, 1992
#include "base/date.h"
#include "base/error.h"
#include "base/bytstrng.h"
#include "base/stream.h"
#include <iostream.h>
#include <ctype.h>
#include <time.h>
#ifdef MSDOS
#include <dos.h>
#endif
#ifdef __GNUC__
#pragma implementation
#endif
// A few static (local) helper functions: IntoDays and IntoYMD
struct DateStruct {
short y,d;
CL_Date::MonthEnum m;
};
static DateStruct IntoYMD (long num_days);
static long IntoDays (const DateStruct&);
CL_DEFINE_CLASS(CL_Date, _CL_Date_CLASSID);
//
// ------------- Constructors and destructors ----------------------
//
// Construct today's date
CL_Date::CL_Date ()
{
_days = 0;
}
/*---------------------------------------------------*/
// Construct the given date, assuming that:
// the year is given as 1992, not 92
// the month is indexed from 1 (e.g. January is month 1)
CL_Date::CL_Date (short year, MonthEnum month, short day)
{
if (!(year >= 1901)) {
CL_Error::Warning ("CL_Date constructor: invalid year %d", year);
_days = 0;
return;
}
if (!(month >= January && month <= December)) {
CL_Error::Warning ("CL_Date constructor: invalid month %d",
month);
_days = 0;
return;
}
if (day < 1 || day > DaysInMonth (month, year)) {
CL_Error::Warning ("CL_Date constructor: invalid day %d", day);
_days = 0;
return;
}
DateStruct my_date;
my_date.y = year;
my_date.m = month;
my_date.d = day;
_days = IntoDays (my_date);
}
/*---------------------------------------------------*/
// Construct the given date, assuming the month specified as a
// string, e.g., "March". Assume case-sensitive comparison and
// completely-specified month names (e.g. "Oct" is not allowed).
CL_Date::CL_Date (short year, const CL_String& month, short day)
{
DateStruct my_date;
my_date.y = year;
my_date.m = MonthNumber (month);
my_date.d = day;
_days = IntoDays (my_date);
}
/*---------------------------------------------------*/
// Construct a date from the given string containing the
// representation in one of the allowed forms.
CL_Date::CL_Date (const CL_String& s)
{
*this = s;
}
void CL_Date::operator= (const CL_String& s)
{
if (!PrepareToChange())
return;
if (s.Size() == 0) {
_days = 0;
Notify ();
return;
}
long d = ParseAndConvert (s);
if (d < 0) {
_days = 0;
Notify ();
return;
}
_days = d;
Notify ();
}
long CL_Date::ParseAndConvert (const CL_String& s)
{
CL_String fld[4];
DateStruct dt;
if (s.Split (fld, 4, " ,") == 3) { // Date_American
fld[0].WordCapitalize ();
dt.m = MonthNumber (fld[0]);
short yr = (short) fld[2].AsLong();
dt.y = (yr >= 1900) ? yr : yr + 1900;
dt.d = (short) fld[1].AsLong();
}
else if (s.Split (fld, 4, "-") == 3) { // Date_Terse
fld[1].WordCapitalize ();
dt.m = MonthNumber (fld[1]);
short yr = (short) fld[2].AsLong();
dt.y = (yr >= 1900) ? yr : yr + 1900;
dt.d = (short) fld[0].AsLong();
}
else if (s.Split (fld, 4, "/") == 3) {// Date_Numbers
dt.m = (MonthEnum) fld[0].AsLong();
dt.y = (short) fld[2].AsLong() + 1900;
dt.d = (short) fld[1].AsLong();
}
else {
// Assume that it's six digits, and try to parse it.
if (s.Size() != 6) {
return -1;
}
for (short i = 0; i < 6; i++) {
if (s[i] > '9' || s[i] < '0') {
return -1;
}
}
short f1 = (s[0]-'0')*10 + s[1]-'0';
short f2 = (s[2]-'0')*10 + s[3]-'0';
short f3 = (s[4]-'0')*10 + s[5]-'0';
if (f1 >= 13) { // Assume yymmdd
dt.m = (MonthEnum) f2;
dt.y = f1 + 1900;
dt.d = f3;
}
else { // Assume mmddyy
dt.m = (MonthEnum) f1;
dt.y = f3 + 1900;
dt.d = f2;
}
}
if (dt.m <= 0 || dt.m >= 13) {
return -1;
}
if (dt.y <= 1899) {
return -1;
}
if (dt.d <= 0 || dt.d >= 32) {
return -1;
}
return IntoDays (dt);
}
/*---------------------------------------------------*/
// Copy constructor
CL_Date::CL_Date (const CL_Date& d)
{
_days = d._days;
}
/*---------------------------------------------------*/
// Destructor
CL_Date::~CL_Date ()
{
}
/*---------------------------------------------------*/
//
// ---------------------- Access ----------------------------------
//
// Return our year
short CL_Date::Year() const
{
return IntoYMD (_days).y;
}
/*---------------------------------------------------*/
// Return our month
CL_Date::MonthEnum CL_Date::Month () const
{
return IntoYMD (_days).m;
}
/*---------------------------------------------------*/
// Return our day of month
short CL_Date::Day () const
{
return IntoYMD (_days).d;
}
/*---------------------------------------------------*/
// Return our day of week. Assume that 1 is for Sunday and 7 for
// Saturday.
CL_Date::WeekdayEnum CL_Date::DayOfWeek () const
{
// Take advantage of the fact that Jan 1, 1901 was a Tuesday.
return (WeekdayEnum) (((2 + _days) % 7) + 1);
}
/*---------------------------------------------------*/
short CL_Date::DaysInMonth () const
{
DateStruct dt = IntoYMD (_days);
return DaysInMonth (dt.m, dt.y);
}
/*---------------------------------------------------*/
CL_String CL_Date::PrintString (DatePrintForm form) const
{
if (_days == 0) // Invalid date
return "";
DateStruct my_date = IntoYMD (_days);
CL_String s, t;
switch (form) {
case Date_American:
s = MonthName (my_date.m) + " "
+ CL_String (my_date.d) + ", "
+ CL_String (my_date.y);
return s;
case Date_Terse:
t = CL_String ((long) my_date.d, 2) + "-";
t = t + ShortMonthName (my_date.m) + "-";
t = t + CL_String ((long) my_date.y);
return t;
case Date_Numbers:
return CL_String ((long) my_date.m, 2, '0') + "/"
+ CL_String ((long) my_date.d, 2, '0') + "/"
+ CL_String ((long) my_date.y - 1900L, 2);
case Date_European:
return CL_String ((long) my_date.d) + " "
+ MonthName (my_date.m) + " "
+ CL_String ((long) my_date.y);
case Date_EuroNumbers:
return CL_String ((long) my_date.d, 2) + "/"
+ CL_String ((long) my_date.m, 2) + "/"
+ CL_String ((long) my_date.y - 1900L);
default:
// CL_Error::Warning ("CL_Date::PrintString: Invalid form %d", form);
return "";
}
}
/*---------------------------------------------------*/
void CL_Date::FromStream (istream& s)
{
CL_String rep;
char c;
long count = 0;
char fill_char = s.fill ();
while (s.get (c) && c == fill_char);
if (!s.good() || s.eof()) {
_days = 0;
return;
}
do {
if (isalnum (c) || c == '/' || c == '-') {
rep.Append (c);
count++;
}
else
break;
} while (s.get (c));
long n = ParseAndConvert (rep);
if (n > 0) {
if (!s.eof ())
s.putback (c);
_days = n;
}
else {
s.seekg (s.tellg() - count, istream::cur);
_days = 0;
}
}
/*---------------------------------------------------*/
// Tell if ours is a leap year
bool CL_Date::IsLeapYear () const
{
return IsLeapYear (IntoYMD (_days).y);
}
/*---------------------------------------------------*/
// Return the date of the next weekday given
CL_Date CL_Date::NextWeekday (const CL_String& weekday_name) const
{
short incr = DayNumber (weekday_name) - DayOfWeek();
return CL_Date (_days + ((incr >= 0) ? incr : incr + 7));
}
/*---------------------------------------------------*/
// Return the date of the previous weekday given
CL_Date CL_Date::PreviousWeekday (const CL_String& weekday_name) const
{
short incr = DayNumber (weekday_name) - DayOfWeek();
return CL_Date (_days - ((incr > 0) ? 7 - incr : -incr));
}
CL_Date CL_Date::NextWeekday (WeekdayEnum weekday_num) const
{
short incr = weekday_num - DayOfWeek();
return CL_Date (_days + ((incr >= 0) ? incr : incr + 7));
}
/*---------------------------------------------------*/
// Return the date of the previous weekday given
CL_Date CL_Date::PreviousWeekday (WeekdayEnum weekday_num) const
{
short incr = weekday_num - DayOfWeek();
return CL_Date (_days - ((incr > 0) ? 7 - incr : -incr));
}
//
// --------------------- Comparison ------------------------------
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?