Date测试

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");
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值