Timestamp.h
#ifndef MUDUO_BASE_TIMESTAMP_H
#define MUDUO_BASE_TIMESTAMP_H
#include <boost/operators.hpp>
#include <iostream>
#include <string>
using namespace std;
namespace muduo
{
class copyable
{
};
class Timestamp : public copyable,
public boost::less_than_comparable<Timestamp>
{
public:
///
/// Constucts an invalid Timestamp.
///
Timestamp()
: microSecondsSinceEpoch_(0)
{
}
///
/// Constucts a Timestamp at specific time
///
/// @param microSecondsSinceEpoch
explicit Timestamp(int64_t microSecondsSinceEpoch);
void swap(Timestamp& that)
{
std::swap(microSecondsSinceEpoch_, that.microSecondsSinceEpoch_);
}
// default copy/assignment/dtor are Okay
string toString() const;
string toFormattedString() const;
bool valid() const { return microSecondsSinceEpoch_ > 0; }
// for internal usage.
int64_t microSecondsSinceEpoch() const { return microSecondsSinceEpoch_; }
time_t secondsSinceEpoch() const
{ return static_cast<time_t>(microSecondsSinceEpoch_ / kMicroSecondsPerSecond); }
///
/// Get time of now.
///
static Timestamp now();
static Timestamp invalid();
static const int kMicroSecondsPerSecond = 1000 * 1000;
private:
int64_t microSecondsSinceEpoch_;
};
inline bool operator<(Timestamp lhs, Timestamp rhs)
{
return lhs.microSecondsSinceEpoch() < rhs.microSecondsSinceEpoch();
}
inline bool operator==(Timestamp lhs, Timestamp rhs)
{
return lhs.microSecondsSinceEpoch() == rhs.microSecondsSinceEpoch();
}
///
/// Gets time difference of two timestamps, result in seconds.
///
/// @param high, low
/// @return (high-low) in seconds
/// @c double has 52-bit precision, enough for one-microseciond
/// resolution for next 100 years.
inline double timeDifference(Timestamp high, Timestamp low)
{
int64_t diff = high.microSecondsSinceEpoch() - low.microSecondsSinceEpoch();
return static_cast<double>(diff) / Timestamp::kMicroSecondsPerSecond;
}
///
/// Add @c seconds to given timestamp.
///
/// @return timestamp+seconds as Timestamp
///
inline Timestamp addTime(Timestamp timestamp, double seconds)
{
int64_t delta = static_cast<int64_t>(seconds * Timestamp::kMicroSecondsPerSecond);
return Timestamp(timestamp.microSecondsSinceEpoch() + delta);
}
}
#endif
Timestamp.cpp
#include <boost/static_assert.hpp>
#include <sys/time.h>
#include <stdio.h>
#include "Timestamp.h"
/*
http://blog.csdn.net/ygm_linux/article/details/25899385
跨平台的:64位整数
*/
#define __STDC_FORMAT_MACROS
#include <inttypes.h> //PRId64
#undef __STDC_FORMAT_MACROS
using namespace muduo;
BOOST_STATIC_ASSERT(sizeof(Timestamp) == sizeof(int64_t));
/*
以微秒初始化microSecondsSinceEpoch_
*/
Timestamp::Timestamp(int64_t microseconds)
: microSecondsSinceEpoch_(microseconds)
{
}
/*
将微秒microSecondsSinceEpoch_ 转换为[秒seconds + 微秒microseconds]
*/
string Timestamp::toString() const
{
char buf[32] = {0};
int64_t seconds = microSecondsSinceEpoch_ / kMicroSecondsPerSecond;
int64_t microseconds = microSecondsSinceEpoch_ % kMicroSecondsPerSecond;
snprintf(buf, sizeof(buf)-1, "%" PRId64 ".%06" PRId64 "", seconds, microseconds);
return buf;
}
/*
将微秒microSecondsSinceEpoch_ 转换为[time_t]
http://blog.csdn.net/csuwzc/article/details/6912104
再利用gmtime_r 将time_t 时间做转换存于 tm_time
*/
string Timestamp::toFormattedString() const
{
char buf[32] = {0};
time_t seconds = static_cast<time_t>(microSecondsSinceEpoch_ / kMicroSecondsPerSecond);
int microseconds = static_cast<int>(microSecondsSinceEpoch_ % kMicroSecondsPerSecond);
struct tm tm_time;
gmtime_r(&seconds, &tm_time);
snprintf(buf, sizeof(buf), "%4d%02d%02d %02d:%02d:%02d.%06d",
tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec,
microseconds);
return buf;
}
/*
将当前时间以微秒存Timestamp类的变量microSecondsSinceEpoch 中;
调用explicit Timestamp(int64_t) 返回
*/
Timestamp Timestamp::now()
{
struct timeval tv;
gettimeofday(&tv, NULL);
int64_t seconds = tv.tv_sec;
return Timestamp(seconds * kMicroSecondsPerSecond + tv.tv_usec);
}
/*
将0 存Timestamp类的变量microSecondsSinceEpoch 中;
调用Timestamp() 返回
*/
Timestamp Timestamp::invalid()
{
return Timestamp();
}
Date.h
#ifndef MUDUO_BASE_DATE_H
#define MUDUO_BASE_DATE_H
#include "Timestamp.h"
struct tm;
namespace muduo
{
///
/// Date in Gregorian calendar.
///
/// This class is immutable.
/// It's recommended to pass it by value, since it's passed in register on x64.
///
class Date : public muduo::copyable
// public boost::less_than_comparable<Date>,
// public boost::equality_comparable<Date>
{
public:
struct YearMonthDay
{
int year; // [1900..2500]
int month; // [1..12]
int day; // [1..31]
};
static const int kDaysPerWeek = 7;
static const int kJulianDayOf1970_01_01;
///
/// Constucts an invalid Date.
///
Date()
: julianDayNumber_(0)
{}
///
/// Constucts a yyyy-mm-dd Date.
///
/// 1 <= month <= 12
Date(int year, int month, int day);
///
/// Constucts a Date from Julian Day Number.
///
explicit Date(int julianDayNum)
: julianDayNumber_(julianDayNum)
{}
///
/// Constucts a Date from struct tm
///
explicit Date(const struct tm&);
// default copy/assignment/dtor are Okay
void swap(Date& that)
{
std::swap(julianDayNumber_, that.julianDayNumber_);
}
bool valid() const { return julianDayNumber_ > 0; }
///
/// Converts to yyyy-mm-dd format.
///
string toIsoString() const;
struct YearMonthDay yearMonthDay() const;
int year() const
{
return yearMonthDay().year;
}
int month() const
{
return yearMonthDay().month;
}
int day() const
{
return yearMonthDay().day;
}
// [0, 1, ..., 6] => [Sunday, Monday, ..., Saturday ]
int weekDay() const
{
return (julianDayNumber_+1) % kDaysPerWeek;
}
int julianDayNumber() const { return julianDayNumber_; }
private:
int julianDayNumber_;
};
inline bool operator<(Date x, Date y)
{
return x.julianDayNumber() < y.julianDayNumber();
}
inline bool operator==(Date x, Date y)
{
return x.julianDayNumber() == y.julianDayNumber();
}
}
#endif // MUDUO_BASE_DATE_H
Date.cpp
#include "Date.h"
#include <stdio.h> // snprintf
namespace muduo{
namespace detail{
char require_32_bit_integer_at_least[sizeof(int) >= sizeof(int32_t) ? 1 : -1];
// algorithm and explanation see:
// http://www.faqs.org/faqs/calendars/faq/part2/
// http://blog.csdn.net/Solstice
int getJulianDayNumber(int year, int month, int day)
{
(void) require_32_bit_integer_at_least; // no warning please
int a = (14 - month) / 12;
int y = year + 4800 - a;
int m = month + 12 * a - 3;
return day + (153*m + 2) / 5 + y*365 + y/4 - y/100 + y/400 - 32045;
}
struct Date::YearMonthDay getYearMonthDay(int julianDayNumber)
{
int a = julianDayNumber + 32044;
int b = (4 * a + 3) / 146097;
int c = a - ((b * 146097) / 4);
int d = (4 * c + 3) / 1461;
int e = c - ((1461 * d) / 4);
int m = (5 * e + 2) / 153;
Date::YearMonthDay ymd;
ymd.day = e - ((153 * m + 2) / 5) + 1;
ymd.month = m + 3 - 12 * (m / 10);
ymd.year = b * 100 + d - 4800 + (m / 10);
return ymd;
}
}
/*格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000*/
const int Date::kJulianDayOf1970_01_01 = detail::getJulianDayNumber(1970, 1, 1);
}
using namespace muduo;
using namespace muduo::detail;
/*
调用getJulianDayNumber
*/
Date::Date(int y, int m, int d)
: julianDayNumber_(getJulianDayNumber(y, m, d))
{
}
Date::Date(const struct tm& t)
: julianDayNumber_(getJulianDayNumber(
t.tm_year+1900,
t.tm_mon+1,
t.tm_mday))
{
}
string Date::toIsoString() const
{
char buf[32];
YearMonthDay ymd(yearMonthDay());
snprintf(buf, sizeof buf, "%4d-%02d-%02d", ymd.year, ymd.month, ymd.day);
return buf;
}
Date::YearMonthDay Date::yearMonthDay() const
{
return getYearMonthDay(julianDayNumber_);
}
test.cpp
#include "Date.h"
#include <assert.h>
#include <stdio.h>
using muduo::Date;
const int kMonthsOfYear = 12;
/*是闰年返回1*/
int isLeapYear(int year)
{
if (year % 400 == 0)
return 1;
else if (year % 100 == 0)
return 0;
else if (year % 4 == 0)
return 1;
else
return 0;
}
/*每月的天数*/
int daysOfMonth(int year, int month)
{
static int days[2][kMonthsOfYear+1] =
{
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
};
return days[isLeapYear(year)][month];
}
void passByConstReference(const Date& x)
{
printf("%s\n", x.toIsoString().c_str());
}
void passByValue(Date x)
{
printf("%s\n", x.toIsoString().c_str());
}
int main()
{
time_t now = time(NULL);
Date someDay(2008, 9, 10);
printf("%s\n", someDay.toIsoString().c_str());
passByValue(someDay);
passByConstReference(someDay);
printf("===================\n");
struct tm t1 = *gmtime(&now);
struct tm t2 = *localtime(&now);
Date todayUtc(t1);
printf("%s\n", todayUtc.toIsoString().c_str());
printf("===================\n");
Date todayLocal(t2);
printf("%s\n", todayLocal.toIsoString().c_str());
printf("===================\n");
int julianDayNumber = 2415021;
int weekDay = 1; // Monday
for (int year = 1900; year < 2500; ++year)
{
/*assert的作用是现计算表达式 expression ,
如果其值为假(即为0),
那么它先向stderr打印一条出错信息,
然后通过调用 abort 来终止程序运行*/
assert(Date(year, 3, 1).julianDayNumber() - Date(year, 2, 29).julianDayNumber()
== isLeapYear(year));
for (int month = 1; month <= kMonthsOfYear; ++month)
{
for (int day = 1; day <= daysOfMonth(year, month); ++day)
{
Date d(year, month, day);
printf("%s %d\n", d.toIsoString().c_str(), d.weekDay());
assert(year == d.year());
assert(month == d.month());
assert(day == d.day());
assert(weekDay == d.weekDay());
assert(julianDayNumber == d.julianDayNumber());
Date d2(julianDayNumber);
assert(year == d2.year());
assert(month == d2.month());
assert(day == d2.day());
assert(weekDay == d2.weekDay());
assert(julianDayNumber == d2.julianDayNumber());
++julianDayNumber;
weekDay = (weekDay+1) % 7;
}
}
}
printf("All passed.\n");
}