gpt4 book ai didi

c++ - boost::locale::date_time 的陷阱

转载 作者:行者123 更新时间:2023-11-30 01:18:18 27 4
gpt4 key购买 nike

您能否提供在 boost 1.55 中使用 boost::locale::date_time 时遇到的陷阱,或者告诉我我在以下示例中犯了什么错误?我是否误解了 boost::locale::date_time API?

day_of_week 示例 1:将日期更改为星期日

#include <iostream>
#include <boost/locale.hpp>

int main() {
using namespace boost::locale;
generator gen;
std::locale locale = gen("en_US.UTF-8");
std::locale::global(locale);
std::cout.imbue(locale);

date_time_period_set s;
s.add(period::year(2013));
s.add(period::month(2));
s.add(period::day(5));
s.add(period::hour(9));
s.add(period::minute(0));
s.add(period::second(0));

// 2013-03-05 is a Tuesday, let's shift it to a Sunday
s.add(period::day_of_week(1));

date_time now(s);// why it's not 2013-03-02 or 2013-03-10?
std::cout << now << std::endl;
}

输出:Mar 30, 2014, 9:00:00 AM,为什么不是 2013-03-02, 9:00:00 AM 2013-03-10,上午 9:00:00?这甚至不是星期天。

day_of_week 示例 2:2013 年 3 月的最后一个星期六

#include <iostream>
#include <boost/locale.hpp>

int main() {
using namespace boost::locale;
generator gen;
std::locale locale = gen("en_US.UTF-8");
std::locale::global(locale);
std::cout.imbue(locale);

date_time_period_set s;
s.add(period::year(2013));
s.add(period::month(2));
s.add(period::hour(9));
s.add(period::minute(0));
s.add(period::second(0));


// swapping the following 2 lines rusults in a wrong date
s.add(period::day_of_week(7));
s.add(period::day_of_week_in_month(-1));


date_time now(s);// last Saturday of March 2013
std::cout << now << std::endl;
}

它输出:Mar 30, 2013, 9:00:00 AM

但如果您更改源代码中标记的 2 行,您可能会看到:Apr 5, 2014, 9:00:00 AM

在哪里以及如何使用 date_time_period boost::locale::period::first_day_of_week(int v)?

参见 date_time_period boost::locale::period::first_day_of_week(int v) .

最佳答案

这不是这个问题的答案。我不太精通 boost::locale::date_time。然而,无论如何我都会用一个可能的替代方案来回应。这种替代方法不像 boost::date_time 那样包装得很好,也没有那么完整,尤其是在语言环境方面。然而,它对您来说可能是一个可行的替代方案,因为您的需求看起来很简单,而这个替代方案非常简单。

我说的是:

chrono-Compatible Low-Level Date Algorithms

这不过是一篇论文,概述了日期(而非时间)计算的 10 个非常低级的构建 block ,例如您问题中的那些。上述论文没有提供您可以下载的库。相反,它只是列出并解释了 10 种算法。每个算法的代码都很短,复制/粘贴到您自己的代码中并根据您的特定需求进行修改非常实用。该代码属于公共(public)领域,因此无需担心版权问题。

本文使用 10 种算法中的 5 种,结合以下用于输出日期的样板(我使用 std::tuple 来保存日期,使用任何你想要的就像),我已经为您的简单问题提出了非常简单的解决方案:

// here is my copy of the 10 algorithms
#include "../date_performance/date_algorithms"
#include <string>
#include <iostream>

// I'm being lazy in defining my date class
using date = std::tuple<int, unsigned, unsigned>;

// I'm being lazy in defining I/O for my date class
std::string
to_string(date const& d)
{
int year;
unsigned month;
unsigned day;
std::tie(year, month, day) = d;
std::string r = std::to_string(year) + '-';
if (month < 10)
r += '0';
r += std::to_string(month) + '-';
if (day < 10)
r += '0';
r += std::to_string(day);
return r;
}

day_of_week 示例 1:将日期更改为星期日

下面是我将如何构造一个日期,例如 2013 年 3 月 5 日:

date d(2013, 3, 5);

为了找到这个日期或之前的星期日,我首先需要找出这个日期是星期几。这是一个使用这些低级构建 block 的两步过程:

  1. 将此日期转换为序列日期:自某个纪元以来的天数。
  2. 将序列日期转换为星期几。

这是通过以下方式完成的:

int s = days_from_civil(std::get<0>(d), std::get<1>(d), std::get<2>(d));
unsigned wd = weekday_from_days(s);

或者如果你愿意:

int s = days_from_civil(2013, 3, 5);
unsigned wd = weekday_from_days(s);

接下来,为一周中的每一天命名常量是个好习惯。此代码遵循 C 和 C++ 约定,例如:

constexpr unsigned sun = 0;

现在是星期日的前一天是序列日期,减去这个工作日过去星期天的天数(如果这是星期日,则可能为 0,如果这个工作日是星期日,则可能为 6周六):

date d1 = civil_from_days(s - weekday_difference(wd, sun));

当我打印出来时:

std::cout << "The Sunday before was " << to_string(d1) << '\n';

我得到:

The Sunday before was 2013-03-03

这是解决您的第一个问题的非常少的代码。相反,如果您想要 2013 年 3 月 5 日之后的星期日,那同样简单:

date d2 = civil_from_days(s + weekday_difference(sun, wd));
std::cout << "The Sunday after was " << to_string(d2) << '\n';

哪些输出:

The Sunday after was 2013-03-10

您可以轻松地使用这些低级算法来编写您自己的高级算法来计算您想要的内容。

day_of_week 示例 2:2013 年 3 月的最后一个星期六

您需要做的第一件事是找到今年该月的最后一天:

unsigned last = last_day_of_month(2013, 3);

在这个例子中我们都知道这等同于:

unsigned last = 31;

但是如果年份和月份是运行时值,last_day_of_month 就派上用场了。现在我们需要这个月最后一天的工作日。和以前一样:

unsigned wd_last = weekday_from_days(days_from_civil(2013, 3, last));

现在我们只需要从 last 中减去最后一个工作日距星期六的天数。假设我们已经设置了一个信息常量 (sat == 6),这看起来像:

unsigned day = last - weekday_difference(wd_last, sat);

day 是 2013 年 3 月的最后一个星期六所在月份的第几天。我们可以将其打印出来:

std::cout << "The last Saturday of March 2013 was " << to_string(date(2013, 3, day)) << '\n';

并得到:

The last Saturday of March 2013 was 2013-03-30

再说一次,您可以轻松地将所有这些封装在一个简洁的函数中。事实上,the paper甚至还有这样一个示例函数。

如果这些低级日期算法对您或任何其他读者有帮助,那就太好了,否则不要紧。 :-)

关于c++ - boost::locale::date_time 的陷阱,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22813668/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com