C++从周数和周日中获取ISO8601日数
C++ Get ISO8601 day number from week number and week day
我有:
- 年份编号(可以是任何年份)
- 月份编号(从1月到12月)
- 周数(第一、第二、第三、第四、最后一周)
- 一周(周日、周一、周二、周三、周四、周五、周六)
我需要得到一个日期编号[从1到~31]-"YYYY-MM-DD"(ISO8601)。
有没有任何方法可以使用boost-poix时间或使用其他一些C++库来计算这一点?
即
- 2014年3月的第一个星期日-那将是2014-03-02
- 2014年12月4日星期三-那将是2014-12-24
谢谢。
我已经编写了一个轻量级的C库,它可以做你想做的事情,有趣的部分在这里,因为你可以看到算法是微不足道的。
#include <stdio.h>
#include <stdint.h>
#include "dt_dow.h"
#include "dt_accessor.h"
const struct test {
int year;
int month; /* Month of the year [1=Jan, 12=Dec] */
int nth; /* Occurrence within month */
dt_dow_t dow; /* Day of the week [1=Mon, 7=Sun] */
int dom; /* Expected day of the month [1, 31] */
} tests[] = {
{ 2014, 3, 1, DT_SUNDAY, 2 },
{ 2014, 4, -1, DT_TUESDAY, 29 },
{ 2014, 4, -2, DT_MONDAY, 21 },
{ 2014, 4, -5, DT_TUESDAY, 1 },
{ 2014, 4, 1, DT_TUESDAY, 1 },
{ 2014, 12, 4, DT_WEDNESDAY, 24 },
};
int
main() {
int i, ntests;
ntests = sizeof(tests) / sizeof(*tests);
for (i = 0; i < ntests; i++) {
const struct test t = tests[i];
{
int dom = dt_dom(dt_from_nth_dow_in_month(t.year, t.month, t.nth, t.dow));
if (t.dom != dom) {
printf("dt_dom(dt_from_nth_dow_in_month(%d, %d, %d, %d))n",
t.year, t.month, t.nth, t.dow);
printf(" got: %dn", dom);
printf(" exp: %dn", t.dom);
}
}
}
return 0;
}
如果你不想使用上面的库/代码,这里有一个重新实现。
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>
bool
leap_year(int y) {
return ((y % 4) == 0 && (y % 100 != 0 || y % 400 == 0));
}
int
days_in_month(int y, int m) {
static const int T[2][13] = {
{ 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 }
};
assert(m >= 1);
assert(m <= 12);
return T[leap_year(y)][m];
}
/* Computes the day of the week [1=Mon, 7=Sun] from the given year, month, day. */
int
ymd_to_dow(int y, int m, int d) {
static const int T[13] = { 0, 6, 2, 1, 4, 6, 2, 4, 0, 3, 5, 1, 3 };
assert(y >= 1);
assert(m >= 1);
assert(m <= 12);
assert(d >= 1);
y -= m < 3;
return 1 + (y + y/4 - y/100 + y/400 + T[m] + d) % 7;
}
int
dom_from_nth_dow_in_month(int y, int m, int nth, int dow) {
int dim, dom;
assert(y >= 1);
assert(m >= 1);
assert(m <= 12);
assert(dow >= 1);
assert(dow <= 7);
dim = days_in_month(y, m);
if (nth > 0) {
dom = 1;
dom += (dow - ymd_to_dow(y, m, dom) + 7) % 7;
dom += --nth * 7;
if (dom <= dim)
return dom;
}
else if (nth < 0) {
dom = dim;
dom -= (ymd_to_dow(y, m, dom) - dow + 7) % 7;
dom -= ++nth * -7;
if (dom >= 1)
return dom;
}
return -1;
}
const struct test {
int year;
int month; /* Month of the year [1=Jan, 12=Dec] */
int nth; /* Occurrence within month */
int dow; /* Day of the week [1=Mon, 7=Sun] */
int dom; /* Expected day of the month [1, 31] */
} tests[] = {
{ 2014, 3, 1, 7, 2 },
{ 2014, 4, -1, 2, 29 },
{ 2014, 4, -2, 1, 21 },
{ 2014, 4, -5, 2, 1 },
{ 2014, 4, 1, 2, 1 },
{ 2014, 12, 4, 3, 24 },
};
int
main() {
int i, ntests;
ntests = sizeof(tests) / sizeof(*tests);
for (i = 0; i < ntests; i++) {
const struct test t = tests[i];
{
int dom = dom_from_nth_dow_in_month(t.year, t.month, t.nth, t.dow);
if (t.dom != dom) {
printf("dom_from_nth_dow_in_month(%d, %d, %d, %d))n",
t.year, t.month, t.nth, t.dow);
printf(" got: %dn", dom);
printf(" exp: %dn", t.dom);
}
}
}
return 0;
}
旧问题的新答案。
使用这个免费的、开源的日期库:
http://howardhinnant.github.io/date_v2.html
2014年,3月的第一个星期日-那将是2014-03-02
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
std::cout << year_month_day{sun[1]/mar/2014} << 'n';
}
输出:
2014-03-02
类型date::year_month_day
上有名为year
、month
和day
的getter。它非常容易使用,并且在上面的链接中有完整的文档。
2014年12月4日星期三-那将是2014-12-24
using namespace date;
std::cout << year_month_day{wed[4]/dec/2014} << 'n';
2014-12-24
但这不是2014年12月的最后一个星期三,这是:
std::cout << year_month_day{wed[last]/dec/2014} << 'n';
2014-12-31
这是图书馆的视频演示。
干得好chansen!这可能真的很有用。但因为我可以自由使用boost——以下是我迄今为止所做的:
// DateFromWeekNumAndDay
// year - Year YYYY.
// weekNum - From 0 to 4.
// weekDay - Week day starts from Sunday - 0 to Saturday - 6.
boost::gregorian::date DateFromWeekNumAndDay(boost::gregorian::date::year_type year, unsigned short weekNum, boost::date_time::weekdays weekDay)
{
boost::gregorian::date date(year, boost::gregorian::Apr, 1);
boost::gregorian::date::day_of_week_type d = date.day_of_week();
date += boost::gregorian::date_duration(weekNum * 7) + boost::gregorian::date_duration(weekDay - d);
return date;
}
就我的测试而言,一切似乎都很好。我从这篇文章中采用了这种方法。因此,感谢用户kebs提供的链接,并非常感谢用户Mikhail Melnik提供的"GetDateFromWeekNumber"函数示例。
相关文章:
- C++为构建时间获取QDateTime的可靠方法
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何使用 < 和 > 命令获取 c++ 中的输入和输出?
- 使用指针从C++中的数组中获取最大值
- 如何获取std::result_of函数的返回类型
- 如何在openssl-ecc中获取十六进制格式的私钥
- 使用Unreal C++获取VR耳机的世界位置/方向
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 从C字符串中获取奇怪的字符串长度
- 为什么我的for循环不能正确获取argv
- 从python中调用C++函数并获取返回值
- 如何获取一个数字的前3位
- 获取字符串的长度并将其分配给数组
- 无法获取菜单选择以运行函数.C++
- 数组长度,为什么从命令行获取时不能使用它?
- Boost Spirit,获取迭代器内部语义动作
- 尝试通过OCI例程从Oracle获取blob数据,但出现错误:ORA-01008:并非所有变量都绑定
- 具有默认值的引用获取函数
- xmake总是报告:错误:无法获取cxx的程序,为什么
- C++从周数和周日中获取ISO8601日数