datetime.cpp
来自「Shorthand是一个强大的脚本语言」· C++ 代码 · 共 826 行 · 第 1/2 页
CPP
826 行
m_time.wDay = atoi(day);
m_time.wYear = atoi(year);
m_time.wHour = atoi(hour);
m_time.wMinute = atoi(min);
m_time.wSecond = atoi(sec);
m_time.wMilliseconds = 0;
if (m_time.wYear < 1000)
{
datetime now;
if (m_time.wYear < 100)
m_time.wYear += (now.m_time.wYear/100)*100;
else
m_time.wYear += (now.m_time.wYear/1000)*1000;
}
m_time.wMonth = 1 + month.index("jan\0feb\0mar\0apr\0may\0jun\0jul\0aug\0sep\0oct\0nov\0dec\0\0");
if (m_time.wMonth == 0) return false;
#ifdef WIN32
FILETIME filetime;
if (!SystemTimeToFileTime(&m_time, &filetime)) return false;
#else
#endif
zone.uppercase();
char ch = zone.cstr()[0];
if (isdigit(ch) || ch == '-' || ch == '+')
{
offset = atoi(zone);
}
else if (zone == "UT" || zone == "GMT") offset = 0;
else if (zone == "EDT") offset = -400;
else if (zone == "EST" || zone == "CDT") offset = -500;
else if (zone == "CST" || zone == "MDT") offset = -600;
else if (zone == "MST" || zone == "PDT") offset = -700;
else if (zone == "PST") offset = -800;
else if (zone == "Z") offset = 0;
else if (zone.length() == 1)
{
// military zone
if (ch >= 'A' && ch <= 'I') offset = - (ch-'A'+1)*100;
else if (ch >= 'K' && ch <= 'M') offset = - (ch-'K'+10)*100;
else if (ch >= 'N' && ch <= 'Y') offset = (ch-'N'+1)*100;
}
// portable zone offset, in minutes
int local_bias = portable_zone_offset();
#ifdef WIN32
// Windows:
__int64 local_adjustment = - ((__int64) local_bias) * 600000000L;
__int64 remote_adjustment = ( (__int64) ((offset/100*60) + offset%100)) * 600000000L;
unsigned __int64 remote_time; memcpy(&remote_time, &filetime, 8);
unsigned __int64 local_time = remote_time - remote_adjustment + local_adjustment;
memcpy(&filetime, &local_time, 8);
FileTimeToSystemTime(&filetime, &m_time);
#else
// Unix:
int local_adjustment = - local_bias * 60;
int remote_adjustment = (offset/100*60 + offset/100)*60;
add_seconds(local_adjustment - remote_adjustment);
#endif
return true;
}
// nullifies date object making it invalid
void datetime::invalidate()
{
memset(&m_time, 0, sizeof(m_time));
}
void datetime::add_days(int days)
{
unsigned int j = jdn() + days;
int y, m, d;
julian2date_relaxed(j, &y, &m, &d);
m_time.wYear = y;
m_time.wMonth = m;
m_time.wDay = d;
}
void datetime::add_seconds(int seconds)
{
int j = jdn();
int tod = m_time.wHour * 3600 + m_time.wMinute*60 + m_time.wSecond;
int days_delta = seconds/86400;
j += days_delta;
tod += seconds%86400;
if (tod > 86400)
{
j++;
tod = tod%86400;
}
else if (tod < 0)
{
j--;
tod = 86400 + tod;
}
unsigned int jdx[2];
jdx[0] = j;
jdx[1] = tod;
import_jdx(jdx);
}
void datetime::export_rfc(string& result)
{
// determine timezone
//struct tm stm; time_t t = time(NULL);
//memcpy(&stm, localtime(&t));
// expires=Fri, 06 Sep 2002 00:07:35 GMT; path=/;
datetime ut = *this;
int ut_offset = portable_zone_offset() * 60;
ut.add_seconds(ut_offset);
int wd = determine_weekday(m_time.wYear, m_time.wMonth, m_time.wDay)%7;
result.printf("%s, %d-%s-%04d %02d:%02d:%02d GMT",
weekday_names[wd], ut.m_time.wDay,
month_names[abs(ut.m_time.wMonth-1)%12],
ut.m_time.wYear,
ut.m_time.wHour,
ut.m_time.wMinute,
ut.m_time.wSecond
);
}
// formats datetime using strftime()-compatible format
void datetime::format(const char* format, string& result) const
{
struct tm stm;
export_stm(&stm);
//
// populate weekday and year's day fields, because
// strftime() relies on what is set in the structure and may
// even chokes on some systems when these fields are incorrect
//
stm.tm_wday = determine_weekday(m_time.wYear, m_time.wMonth, m_time.wDay)%7;
stm.tm_yday = 1 + abs(jdn() - get_year_start(m_time.wYear))%366;
stm.tm_isdst = daylight;
#if !defined(WIN32) && !defined(SOLARIS)
stm.tm_gmtoff = 0;
stm.tm_zone = tzname[daylight%2];
#endif
char buf[512];
if (strftime(buf, sizeof(buf), format, &stm) == 0)
{
throw new ShhObjectException(4107, "Date format is too long");
}
result = buf;
}
// exports value into "extended Julian" format which is
// array of two integer number {JDN,seconds_since_midnight}
void datetime::export_jdx(unsigned int* jdx) const
{
jdx[0] = jdn();
jdx[1] = m_time.wHour * 3600 + m_time.wMinute*60 + m_time.wSecond;
}
void datetime::import_ydm(int year, int month, int day)
{
m_time.wHour = 0;
m_time.wMinute = 0;
m_time.wSecond = 0;
m_time.wYear = year;
m_time.wMonth = month;
m_time.wDay = day;
}
// imports JDN
void datetime::import_jdn(int jdn)
{
if (jdn < 0)
throw new ShhObjectException(4108, "Cannot convert number %d to date", jdn);
else
{
m_time.wHour = 0;
m_time.wMinute = 0;
m_time.wSecond = 0;
int y,d,m;
julian2date_strict(jdn, &y, &m, &d);
m_time.wYear = y;
m_time.wMonth = m;
m_time.wDay = d;
}
}
// imports value from "extended Julian" format which is
// array of two integer number {JDN,seconds_since_midnight}
void datetime::import_jdx(const unsigned int* jdx)
{
int y,d,m;
julian2date_relaxed(jdx[0], &y, &m, &d);
m_time.wYear = y;
m_time.wMonth = m;
m_time.wDay = d;
int secs = jdx[1];
m_time.wHour = secs/3600; secs -= (m_time.wHour * 3600);
m_time.wMinute = (secs/60); secs -= (m_time.wMinute * 60);
m_time.wSecond = secs;
}
// returns JDN of the date
unsigned int datetime::jdn() const
{
return date2julian_relaxed(m_time.wYear, m_time.wMonth, m_time.wDay);
}
// returns number of seconds since midnight on the specified date
unsigned int datetime::seconds_since_midnight() const
{
return m_time.wHour*3600 + m_time.wMinute * 60 + m_time.wSecond;
}
const datetime& datetime::operator = (const datetime& other)
{
memcpy(&m_time, &other.m_time, sizeof(SYSTEMTIME));
return *this;
}
// converts month number to 3-letter abbreviation
const char* datetime::month3(int month)
{
switch(month)
{
case 1: return "Jan";
case 2: return "Feb";
case 3: return "Mar";
case 4: return "Apr";
case 5: return "May";
case 6: return "Jun";
case 7: return "Jul";
case 8: return "Aug";
case 9: return "Sep";
case 10: return "Oct";
case 11: return "Nov";
case 12: return "Dec";
default: return "";
}
}
// prints datetime in "common" format: "22 Jul 2002, 6:17 AM"
void datetime::common_print(string& s) const
{
const char* ampm = (m_time.wHour < 12) ? "AM" : "PM";
int hour = m_time.wHour%12;
if (hour == 0) hour = 12;
s.printf("%d %s %d, %d:%02d %s",
m_time.wDay, month3(m_time.wMonth), m_time.wYear, hour, m_time.wMinute, ampm
);
}
/** returns difference in days between two dates, disregarding time-of-day parts */
int day_difference(const datetime& one, const datetime& two)
{
return one.jdn() - two.jdn();
}
/**
* returns -1, 0, or +1 depending on whether date one is less, equals, or
* greater than date two.
* all components are considered, up to seconds.
*/
int compare_dates(const datetime& one, const datetime& two)
{
int daydiff = one.jdn() - two.jdn();
if (daydiff != 0) return daydiff > 0 ? 1 : -1;
int secdiff = one.seconds_since_midnight() - two.seconds_since_midnight();
if (secdiff == 0) return 0;
else if (secdiff < 0) return -1;
else return 1;
}
// imports value from variety of string formats by trying
// to guess fields automatically
bool datetime::import_any(const char* s)
{
return false; // not implemented yet
}
#define DX(x) ((int)((x)-'0'))
#define DX2(x) DX(x[0])*10 + DX(x[1])
/**
* imports date/time from any of formats returned by MySQL
* (DATE,TIME,DATETIME or any TIMESTAMP)
*/
bool datetime::import_mysql(const char* input)
{
// date+time specification with optional time
RX datetime_rx(
"([0-9]{1,4})[^0-9]+([0-9]{1,2})[^0-9]+([0-9]{1,2})( +([0-9]{1,2})[^0-9]+([0-9]{1,2})[^0-9]+([0-9]{1,2}))?",
RXX_NO_BK_PARENS|RXX_NO_BK_VBAR|RXX_INTERVALS|RXX_NO_BK_BRACES
);
// time-only specification
RX time_rx(
"([0-9]{1,2})[^0-9]+([0-9]{1,2})([^0-9]+([0-9]{1,2}))?",
RXX_NO_BK_PARENS|RXX_NO_BK_VBAR|RXX_INTERVALS|RXX_NO_BK_BRACES
);
memset(&m_time, 0, sizeof(m_time));
local();
m_time.wMilliseconds = 0;
if (time_rx.match(input))
{
string s;
time_rx.submatch(1, s); m_time.wHour = atoi(s);
time_rx.submatch(2, s); m_time.wMinute = atoi(s);
time_rx.submatch(3, s); m_time.wSecond = atoi(s);
return true;
}
else if (datetime_rx.match(input))
{
string s;
datetime_rx.submatch(1, s); m_time.wYear = atoi(s);
datetime_rx.submatch(2, s); m_time.wMonth = atoi(s);
datetime_rx.submatch(3, s); m_time.wDay = atoi(s);
datetime_rx.submatch(5, s); m_time.wHour = atoi(s);
datetime_rx.submatch(6, s); m_time.wMinute = atoi(s);
datetime_rx.submatch(7, s); m_time.wSecond = atoi(s);
return true;
}
else
{
bool only_digits = true;
int n = strlen(input);
// timstampes returned by SQL must have even number of characters
if (n%2 != 0 || n == 0 || n > 14) return false;
for(int i=0; i<n; i++)
{
if (!isdigit(input[i])) { only_digits = false; break; }
}
if (!only_digits) return false /* sorry */;
// import format depends on the length
// 14: YYYYMMDDHHMMSS
// 12: YYMMDDHHMMSS
// 10: YYMMDDHHMM
// 8: YYYYMMDD
// 6: YYMMDD
// 4: YYMM
// 2: YY
const char* p = input;
if (n == 8 || n == 14)
{
m_time.wYear = DX(p[0])*1000 + DX(p[1])*100 + DX(p[2])*10 + DX(p[3]);
p += 4;
}
else
{
m_time.wYear = (m_time.wYear/100)*100 + DX2(p);
p += 2;
}
if (n >= 4) { m_time.wMonth = DX2(p); p+= 2;} else m_time.wMonth = 1;
if (n >= 6) { m_time.wDay = DX2(p); p+= 2;} else m_time.wDay = 1;
if (n >= 10) { m_time.wHour = DX2(p); p+= 2;} else m_time.wHour = 0;
if (n >= 10) { m_time.wMinute = DX2(p); p+= 2;} else m_time.wMinute = 0;
if (n >= 12) { m_time.wSecond = DX2(p); p+= 2;} else m_time.wSecond = 0;
m_time.wMilliseconds = 0;
return true;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?