写出下面这段晦涩难懂但却极为高效的代码的人,真是个败类。
// For more information about Year 2038 problem please refer to
// http://en.wikipedia.org/wiki/Year_2038_problem
#include <iostream>
#include <ctime>
#include <cassert>
using namespace std;
class DateTime
{
public:
DateTime(int year, int month, int day, int hour, int minute, int second)
{
assert(year >= 1970 && year <= 2038);
assert(month >= 1 && month <= 12);
assert(day >= 1);
assert(hour >= 0 && hour <= 23);
assert(minute >= 0 && minute <= 59);
assert(second >= 0 && second <= 59);
switch(month){
case 4:
case 6:
case 9:
case 11:
assert(day <= 30);
break;
case 2:
if(year % 4 == 0)
assert(day <= 29);
else
assert(day <= 28);
break;
default:
assert(day <= 31);
}
// 4 years
timeStamp = secondsEvery4Years * ((year - 1970) / 4);
// year
timeStamp += ((year - 1970) % 4) * secondsPerDay * 365;
// add one day if Feb 29 included
if(((year - 1970) % 4) * 12 + month > 12 + 12 + 2) // if contains a Feb 29 in the last 4-year-cycle
timeStamp += secondsPerDay;
// month
static const int daysInMonth[11] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30};
for(; month > 1; month--)
timeStamp += daysInMonth[month - 2] * secondsPerDay;
// day
timeStamp += (day - 1) * secondsPerDay;
// hour
timeStamp += hour * secondsPerHour;
// minute
timeStamp += minute * secondsPerMinute;
// second
timeStamp += second;
assert(timeStamp >= 0 && timeStamp <= 0x7fffffff);
}
// overload constructor
DateTime(time_t t)
{
assert(t >= 0 && t <= 0x7fffffff);
timeStamp = t;
}
time_t GetTimeStamp()
{
return timeStamp;
}
int GetYear()
{
int year = 1970 + (timeStamp / secondsEvery4Years) * 4;
int remain = timeStamp % secondsEvery4Years;
if(remain < 365 * 2 * secondsPerDay)
year += remain / (secondsPerDay * 365);
else if(remain < (365 * 2 + 366) * secondsPerDay)
year += 2;
else
year += 3;
return year;
}
void GetDate(int* month, int* day)
{
assert(month != NULL && day != NULL);
static const int sumNormal[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
static const int sumLeapYear[13] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
const int *sumDays = sumNormal;
int remain = timeStamp % secondsEvery4Years;
if(remain < secondsPerDay * (365 * 2 + 31 + 28))// 1st year 1-1 ~ 3rd year 2-28
remain %= secondsPerDay * 365;
else if(remain < secondsPerDay * (365 * 3 + 1)){ // 3rd year 2-29 ~ 3rd year 12-31
remain -= secondsPerDay * (365 * 2);
sumDays = sumLeapYear; // has Feb 29
}
else// 4th year 1-1 ~ 4th year 12-31
remain -= secondsPerDay * (365 * 2 + 366);
int idx = remain / (secondsPerDay * 29);
*month = remain >= sumDays[idx] * secondsPerDay ? idx + 1 : idx;
remain -= sumDays[*month - 1] * secondsPerDay;
*day = remain / secondsPerDay + 1;
}
// 0:Sunday, 1:Monday, , 6:Saturday
int GetDayOfWeek()
{
return (timeStamp % secondsPerWeek / secondsPerDay + 4) % 7;
}
int GetHour()
{
return timeStamp % secondsPerDay / secondsPerHour;
}
int GetMinute()
{
return timeStamp % secondsPerHour / secondsPerMinute;
}
int GetSecond()
{
return timeStamp % secondsPerMinute;
}
virtual void Display()
{
int month, day;
static const char* days[7] = {"Sun", "Mon", "Tue", "Wed", "Tur", "Fri", "Sat"};
GetDate(&month, &day);
cout<< GetYear() << '-' << month << '-' << day << ' '
<< days[GetDayOfWeek()] << ' ' << GetHour() << ':' << GetMinute() << ':' << GetSecond() << endl;
}
private:
time_t timeStamp;
static const int secondsPerMinute = 60;
static const int secondsPerHour = secondsPerMinute * 60;
static const int secondsPerDay = secondsPerHour * 24;
static const int secondsPerWeek = secondsPerDay * 7;
static const int secondsEvery4Years = secondsPerDay * (365 * 3 + 366);
};
// TimeFly is a class for testing DateTime
// It covers all the valid cases
class TimeFly
{
public:
TimeFly():year(1970), month(1), day(1), dayOfWeek(4), hour(0), minute(0), second(0), timeStamp(0)
{}
virtual void Display()
{
static const char* days[7] = {"Sun", "Mon", "Tue", "Wed", "Tur", "Fri", "Sat"};
cout<< year << '-' << month << '-' << day << ' '
<< days[dayOfWeek] << ' ' << hour << ':' << minute << ':' << second << endl;
}
bool DayChanges()
{
dayOfWeek = ++dayOfWeek % 7;
static int daysInMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 1970 has no Feb29
if(++day > daysInMonth[month]){
day = 1;
if(++month > 12){
month = 1;
daysInMonth[2] = ++year % 4 ? 28 : 29;
cout << year << endl;
}
}
return true;
}
void HowTimeFlies()
{
while(year != 2038 || day != 19 || minute != 14 || second != 7 || hour != 3){
(second = ++second % 60) || (minute = ++minute % 60) || (hour = ++hour % 24) || DayChanges();
timeStamp++;
DateTime dt = DateTime(year, month, day, hour, minute, second);
int m, d;
dt.GetDate(&m, &d);
if(dt.GetYear() != year || m != month || d != day || dt.GetDayOfWeek() != dayOfWeek || dt.GetHour() != hour || dt.GetMinute() != minute || dt.GetSecond() != second || dt.GetTimeStamp() != timeStamp){
cout << "TimeFly" << endl;
Display();
cout << "DateTime" << endl;
dt.Display();
}
}
}
private:
int second;
int minute;
int hour;
int dayOfWeek;
int day;
int month;
int year;
int timeStamp;
};
int main()
{
TimeFly fly;
fly.HowTimeFlies();
return 0;
}
// http://en.wikipedia.org/wiki/Year_2038_problem
#include <iostream>
#include <ctime>
#include <cassert>
using namespace std;
class DateTime
{
public:
DateTime(int year, int month, int day, int hour, int minute, int second)
{
assert(year >= 1970 && year <= 2038);
assert(month >= 1 && month <= 12);
assert(day >= 1);
assert(hour >= 0 && hour <= 23);
assert(minute >= 0 && minute <= 59);
assert(second >= 0 && second <= 59);
switch(month){
case 4:
case 6:
case 9:
case 11:
assert(day <= 30);
break;
case 2:
if(year % 4 == 0)
assert(day <= 29);
else
assert(day <= 28);
break;
default:
assert(day <= 31);
}
// 4 years
timeStamp = secondsEvery4Years * ((year - 1970) / 4);
// year
timeStamp += ((year - 1970) % 4) * secondsPerDay * 365;
// add one day if Feb 29 included
if(((year - 1970) % 4) * 12 + month > 12 + 12 + 2) // if contains a Feb 29 in the last 4-year-cycle
timeStamp += secondsPerDay;
// month
static const int daysInMonth[11] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30};
for(; month > 1; month--)
timeStamp += daysInMonth[month - 2] * secondsPerDay;
// day
timeStamp += (day - 1) * secondsPerDay;
// hour
timeStamp += hour * secondsPerHour;
// minute
timeStamp += minute * secondsPerMinute;
// second
timeStamp += second;
assert(timeStamp >= 0 && timeStamp <= 0x7fffffff);
}
// overload constructor
DateTime(time_t t)
{
assert(t >= 0 && t <= 0x7fffffff);
timeStamp = t;
}
time_t GetTimeStamp()
{
return timeStamp;
}
int GetYear()
{
int year = 1970 + (timeStamp / secondsEvery4Years) * 4;
int remain = timeStamp % secondsEvery4Years;
if(remain < 365 * 2 * secondsPerDay)
year += remain / (secondsPerDay * 365);
else if(remain < (365 * 2 + 366) * secondsPerDay)
year += 2;
else
year += 3;
return year;
}
void GetDate(int* month, int* day)
{
assert(month != NULL && day != NULL);
static const int sumNormal[13] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
static const int sumLeapYear[13] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
const int *sumDays = sumNormal;
int remain = timeStamp % secondsEvery4Years;
if(remain < secondsPerDay * (365 * 2 + 31 + 28))// 1st year 1-1 ~ 3rd year 2-28
remain %= secondsPerDay * 365;
else if(remain < secondsPerDay * (365 * 3 + 1)){ // 3rd year 2-29 ~ 3rd year 12-31
remain -= secondsPerDay * (365 * 2);
sumDays = sumLeapYear; // has Feb 29
}
else// 4th year 1-1 ~ 4th year 12-31
remain -= secondsPerDay * (365 * 2 + 366);
int idx = remain / (secondsPerDay * 29);
*month = remain >= sumDays[idx] * secondsPerDay ? idx + 1 : idx;
remain -= sumDays[*month - 1] * secondsPerDay;
*day = remain / secondsPerDay + 1;
}
// 0:Sunday, 1:Monday, , 6:Saturday
int GetDayOfWeek()
{
return (timeStamp % secondsPerWeek / secondsPerDay + 4) % 7;
}
int GetHour()
{
return timeStamp % secondsPerDay / secondsPerHour;
}
int GetMinute()
{
return timeStamp % secondsPerHour / secondsPerMinute;
}
int GetSecond()
{
return timeStamp % secondsPerMinute;
}
virtual void Display()
{
int month, day;
static const char* days[7] = {"Sun", "Mon", "Tue", "Wed", "Tur", "Fri", "Sat"};
GetDate(&month, &day);
cout<< GetYear() << '-' << month << '-' << day << ' '
<< days[GetDayOfWeek()] << ' ' << GetHour() << ':' << GetMinute() << ':' << GetSecond() << endl;
}
private:
time_t timeStamp;
static const int secondsPerMinute = 60;
static const int secondsPerHour = secondsPerMinute * 60;
static const int secondsPerDay = secondsPerHour * 24;
static const int secondsPerWeek = secondsPerDay * 7;
static const int secondsEvery4Years = secondsPerDay * (365 * 3 + 366);
};
// TimeFly is a class for testing DateTime
// It covers all the valid cases
class TimeFly
{
public:
TimeFly():year(1970), month(1), day(1), dayOfWeek(4), hour(0), minute(0), second(0), timeStamp(0)
{}
virtual void Display()
{
static const char* days[7] = {"Sun", "Mon", "Tue", "Wed", "Tur", "Fri", "Sat"};
cout<< year << '-' << month << '-' << day << ' '
<< days[dayOfWeek] << ' ' << hour << ':' << minute << ':' << second << endl;
}
bool DayChanges()
{
dayOfWeek = ++dayOfWeek % 7;
static int daysInMonth[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};// 1970 has no Feb29
if(++day > daysInMonth[month]){
day = 1;
if(++month > 12){
month = 1;
daysInMonth[2] = ++year % 4 ? 28 : 29;
cout << year << endl;
}
}
return true;
}
void HowTimeFlies()
{
while(year != 2038 || day != 19 || minute != 14 || second != 7 || hour != 3){
(second = ++second % 60) || (minute = ++minute % 60) || (hour = ++hour % 24) || DayChanges();
timeStamp++;
DateTime dt = DateTime(year, month, day, hour, minute, second);
int m, d;
dt.GetDate(&m, &d);
if(dt.GetYear() != year || m != month || d != day || dt.GetDayOfWeek() != dayOfWeek || dt.GetHour() != hour || dt.GetMinute() != minute || dt.GetSecond() != second || dt.GetTimeStamp() != timeStamp){
cout << "TimeFly" << endl;
Display();
cout << "DateTime" << endl;
dt.Display();
}
}
}
private:
int second;
int minute;
int hour;
int dayOfWeek;
int day;
int month;
int year;
int timeStamp;
};
int main()
{
TimeFly fly;
fly.HowTimeFlies();
return 0;
}
原谅我把上面的c++代码写得血肉模糊。因为C/C++如果不这么耍,就没意思了。
由于c#本身执行效率低,所以一定要注重表达,否则就真的没法混了。以下是逻辑明晰的c#代码,它完成了和上面c++编写的DateTime类一样的功能,而且完成得更出色,请看:
public static DateTime ParseUnixTimeStamp(int timeStamp)
{
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return dt.AddSeconds(timeStamp); ;
}
public static int GetUnixTimeStamp(DateTime dt)
{
DateTime dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
TimeSpan span = dt - dt1970;
return (int)(span.TotalSeconds);
}
你是不是要说,C#真是个败类。
{
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return dt.AddSeconds(timeStamp); ;
}
public static int GetUnixTimeStamp(DateTime dt)
{
DateTime dt1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
TimeSpan span = dt - dt1970;
return (int)(span.TotalSeconds);
}