【问题标题】:Find the exact date and time before n months?找出 n 个月之前的确切日期和时间?
【发布时间】:2016-12-17 12:54:42
【问题描述】:

我在我的项目中使用HowardHinnant date 库。我想得到 n 个月之前的确切日期时间。

例如:“2016-12-17 18:21:26”是当前日期时间,我想知道 13 个月前的日期时间。它应该输出“2015-11-17 18:21:26”。

/*
 * This function will return the current date in year_month_day format
 */

auto currentDate() {
    auto currentTime = std::chrono::system_clock::now();
    date::year_month_day currentDate = date::floor<date::days>(currentTime);
    return currentDate;
}



/*
 * This function will find the date before (n) months
 */

template <typename T>
auto oldDate(T monthsNum) {
    auto currentDate = currentDate();
    auto yearCurrentDate = (int)currentDate.year();
    auto monthCurrentDate = currentDate.month();
    auto dayCurrentDate = currentDate.day();
    auto yearNum = monthsNum/12;
    auto yearEndDate = yearCurrentDate - yearNum;
    auto monthNum = monthsNum%12;
    auto monthEndDate = monthCurrentDate;
    while(monthNum) {
        monthEndDate--;
    }
    if(monthEndDate > monthCurrentDate) {
        yearEndDate--;
    }
    date::year_month_day endDate = date::year{yearEndDate}/monthEndDate;
    return endDate;
}

我的函数oldDate() 将返回几个月前n 的日期。但我无法获得时间。

【问题讨论】:

  • 如果没有这样的日期怎么办? 2016-03-31 18:21:26的前一个月?
  • @W.F. :在这种情况下,它应该返回该月和该年的最后日期。但是我的函数目前没有处理这种情况。

标签: c++ datetime c++11 chrono


【解决方案1】:

创建一个currentTime,而不是currentDate(),它返回一个sys_seconds(时间精度为秒):

auto
currentTime()
{
    using namespace std::chrono;
    return date::floor<seconds>(system_clock::now());
}

现在oldDate 可以调用currentTime 而不是currentDate,这样就可以知道并保存一天中的时间。

oldDate 应该将date::months 作为参数,这是一个精度为月的std::chrono::duration。下面是它的样子(稍后描述):

auto
oldDate(date::months monthsNum)
{
    using namespace date;
    auto time = currentTime();
    auto sd = floor<days>(time);
    auto time_of_day = time - sd;
    auto ymd = year_month_day{sd} - monthsNum;
    if (!ymd.ok())
        ymd = ymd.year()/ymd.month()/last;
    return sys_days{ymd} + time_of_day;
}

using namespace date 很方便,否则你会到处都有date::

  • 首先从currentTime() 获取时间。这是std::chrono::time_point&lt;system_clock, seconds&gt;,或自 1970-01-01 UTC 以来的秒数。

  • 然后使用floor&lt;days&gt;() 将此秒数截断为天数。这是std::chrono::time_point&lt;system_clock, days&gt;

  • 可以将sd 视为一天中第一个瞬间的时间点(以UTC 表示)。所以如果你从time 中减去sd,你会得到一个代表一天中时间的std::chrono::duration。精度将是您要减去的两个精度中的common_type (seconds)。

  • 要进行月份运算,您需要将sd 的类型从sys_daystime_point)切换为year_month_day(日历类型)。一旦你输入了year_month_day,你就可以从中减去monthsNum,得到另一个year_month_day(存储在上面的ymd中)。

  • 您可以使用.ok() 检查这是否导致有效日期。如果它是无效日期,则意味着您溢出了year_month_day 的天数字段。我在 cmets 中看到,如果发生这种情况,您需要本月的最后一天。因此,只需提取 yearmonth 并使用 lastymd 重置为该年月的最后一天。

  • 最后将ymd 转换回sys_daystime_point 精度为days)并将time_of_day 添加回它。

结果是sys_secondstime_pointseconds 精度)。

我刚刚用这个驱动程序运行了这个:

int
main()
{
    using namespace date;
    std::cout << currentTime() << '\n';
    std::cout << oldDate(months{13}) << '\n';
}

输出是:

2016-12-17 15:57:52
2015-11-17 15:57:52

Convenience link to documentation.

【讨论】:

  • 在一个答案中看到如此详细的内容后,我删除了我的答案。除了编程部分之外,我还从这个答案中学到了很多东西:)
猜你喜欢
  • 1970-01-01
  • 2011-05-31
  • 1970-01-01
  • 2021-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 2018-09-28
相关资源
最近更新 更多