我们要求从tm_yday派生日期;一年中的一天(从1月1日起)和tm_year;自1900年以来的几年。
任何人都可以提供帮助。
我已经尝试但没有运气感谢你的帮助任何方向也会有所帮助。
例如输入300 1900的值应该是10/27/1900,其中300是一年中的一天和1900年。
提前致谢!
答案 0 :(得分:0)
你需要实际执行此操作,不要涉及ctime
和mktime
的变幻莫测,这在这种情况下是不合适的,因为tm_yday
的值是< em> not 用于构建时间(根据其他字段的值设置tm_wday
和tm_yday
,并根据需要调整它们。
为此,我们可以简单地使用以下代码作为起点。它实际上使用的数组包含每个月的天数,当然是将2月调整为闰年。
然后通过从一年中提供的日期连续减去每个月的天数,直到它比当月的天数少,就可以计算出您所在的月份。
在该过程结束时,月份和日期已知,我们只需输出值:
#include <iostream>
#include <cstdlib>
// Function to detect leap year.
bool isLeapYear(int year) {
if (year % 400 == 0) return true;
if (year % 100 == 0) return false;
if (year % 4 == 0) return true;
return false;
}
// Helper function for parameter checks.
int usageExit(const char *errMsg) {
std::cerr << "*** " << errMsg << std::endl;
std::cerr << "Usage: getdate <year> <day-of-year>" << std::endl;
return 1;
}
int main(int argc, char *argv[]) {
// Must provide two parameters.
if (argc != 3) return usageExit("Incorrect parameter count");
// Get (and check) year and day of year.
char *firstBad;
long year = std::strtol(argv[1], &firstBad, 10);
if ((firstBad == argv[1]) || (*firstBad != '\0')) return usageExit("Year is not numeric");
if (year < 0) return usageExit("Year is negative");
bool leapYear = isLeapYear(year);
long dayOfYear = std::strtol(argv[2], &firstBad, 10);
if ((firstBad == argv[2]) || (*firstBad != '\0')) return usageExit("Day of year is not numeric");
if ((dayOfYear < 1) || (dayOfYear > (leapYear ? 366 : 365))) return usageExit("Day of year is out of range");
// Figure out month and day of month, from day of year.
int daysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if (leapYear) daysInMonth[1]++;
int month = 0;
int daysLeft = dayOfYear;
while (daysLeft > daysInMonth[month])
daysLeft -= daysInMonth[month++];
++month;
// Output results.
std::cout << month << "/" << daysLeft << "/" << year << std::endl;
}
答案 1 :(得分:0)
这可以在没有迭代/分支算法的情况下完成,这将使其更有效。 algorithms are given here。Howard Hinnant's free, open-source C++11/14/17 date/time library。我们的想法是,您可以将三元组:{year, jan, 1}
转换为连续天数,将该天数添加到该计数天数,然后将该总和转换回{year, month, day}
。
days_from_civil
algorithm基于这些无迭代算法,并提供简洁可读的语法来调用它们。该语法如下所示。但首先要谈谈tm_yday
:
tm_yday
由C标准定义为:
自1月1日起的天数 - [0,365]
也就是说,1月1日是第0天。但是这句话:
例如输入300 1900的值应为10/27/1900
将1月1日定义为第1天。因此,在下面的代码中,1
从tm_yday
中减去,将1月1解释为第1天,将{300, 1900}
解释为1900-10-27。如果不希望对tm_yday
进行此解释,请删除- 1
。
#include "date/date.h"
date::year_month_day
f(const std::tm& x)
{
using namespace date;
return sys_days{year{x.tm_year + 1900}/jan/1} + days{x.tm_yday-1};
}
date::year_month_day
是一个{year, month, day}
结构,每个字段都有getter。此函数从tm_year
检索tm_yday
和std::tm
字段,并使用以下步骤将它们转换为year_month_day
:
year{x.tm_year + 1900}
将tm_year
字段转换为名为date::year
的字段。这只不过是一个short
的包装器,意味着一年。它可以保存[-32767,32767]范围内的值。
表达式year{x.tm_year + 1900}/jan/1
为所示年份的1月1日构建date::year_month_day
。它只存储年,月和日的三个值,不进行其他计算。
date::sys_days
是天数。它实际上是基于std::chrono::time_point
的{{1}},精度为system_clock
(相对于微秒或纳秒)。 days
使用civil_from_days
algorithm将sys_days{...}
转换为此year_month_day
(天数)。
time_point
是date::days
,期限为24小时。表达式std::chrono::duration
将指示的整数表达式转换为名为days{x.tm_yday-1}
的{{1}}类型。
duration
的{{1}}被添加到代表一年中第一天的日精度days
。
总和的结果是新的duration
持有另一天的天数。使用Firestore documentation on working with arrays, lists and sets将days
隐式转换回函数time_point
的返回类型。
这个功能可以像这样运用:
time_point
输出:
time_point
如果您在year_month_day
的任何优化高于std::tm tm{};
tm.tm_yday = 300;
std::cout << f(tm) << '\n';
时使用1900-10-27
编译f
,它将编译为无分支对象代码没有桌子。这样的代码非常缓存友好且管道友好。对于奖励积分,clang
的定义在人眼中也很容易。