最便携和最可靠的方法是使用 ANSI C mktime 和 localtime 函数,它们可以与 C 或 C++ 一起使用
更新:
要回答有关如何实现自己的算法而不是使用标准 C 库 mktime 函数的问题,一个很好的起点是查看已知的工作代码,例如glibc mktime 源代码。您需要的相关花絮包括:
从glibc 2.17 (HEAD) mktime.c第 141 行开始:
#define TM_YEAR_BASE 1900
/* Return 1 if YEAR + TM_YEAR_BASE is a leap year. */
static inline int
leapyear (int year)
{
/* Don't add YEAR to TM_YEAR_BASE, as that might overflow.
Also, work even if YEAR is negative. */
return
((year & 3) == 0
&& (year % 100 != 0
|| ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
}
从glibc 2.17 (HEAD) mktime.c第 160 行开始:
const unsigned short int __mon_yday[2][13] =
{
/* Normal years. */
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
/* Leap years. */
{ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
};
实现将 year 和 dayOfYear 转换为相应的 month 和 dayOfMonth 的构造函数的示例 C++ 类可能类似于:
#include <iostream>
using namespace std;
#define MONTHS_IN_YEAR 12
class MyDateClass {
public:
MyDateClass(int year, int dayOfYear) {
int yearOffset = dayOfYear - TM_YEAR_BASE;
int leapYearIndex = leapyear(year) ? 1 : 0;
int daysInYear = leapYearIndex ? 366 : 365;
this->year = year;
this->dayOfYear = dayOfYear;
if (dayOfYear >= 1 && dayOfYear <= daysInYear) {
for (int mon = 0; mon < MONTHS_IN_YEAR; mon++) {
if (dayOfYear <= __mon_yday[leapYearIndex][mon+1]) {
month = mon + 1;
dayOfMonth = dayOfYear - __mon_yday[leapYearIndex][mon];
break;
}
}
} else {
cerr << "day of year must be between 1 and " << daysInYear << endl;
month = 0;
dayOfMonth = 0;
}
}
// Get month 1=January, 12=December
inline int getMonth() { return month; }
// Get day of month
inline int getDayOfMonth() { return dayOfMonth; }
// Get year
inline int getYear() { return year; }
// Get day of yar
inline int getDayOfYear() { return dayOfYear; }
private:
int month;
int dayOfMonth;
int year;
int dayOfYear;
};
希望我不会因为展示可能完成这项工作的示例代码而被否决。当然,您可以随意实现它。这只是一种示例方法。
如果您更愿意使用现有的 mktime 功能(推荐),它很可能存在于您正在编程的任何平台上的标准 C 库中,我的原始答案内容如下...
使用 mktime 时,您需要确保将 tm_mon=0 和 tm_mday 设置为一年中的某一天(请参阅 mktime 文档以获得更好的解释),但简而言之,mktime 忽略 tm_wday 和 tm_yday 并且只翻译 tm_mday,它基本上解释为如果您还设置了 tm_mon = 0,则为一年中的某一天;
以下是一些说明这一点的工作示例代码,可以在 C 或 C++ 中工作:
#include <stdio.h> /* printf, scanf */
#include <time.h> /* time_t, struct tm, time, mktime */
#include <strings.h> /* bzero */
int main () {
time_t loctime;
struct tm timeinfo, *loctimeinfo;
int year, day;
/* prompt user for year and day-of-the-year */
printf ("Enter year: "); scanf ("%d",&year);
printf ("Enter day of the year: "); scanf ("%d",&day);
/* initialize timeinfo and modify it to the user's choice */
bzero(&timeinfo, sizeof(struct tm));
timeinfo.tm_isdst = -1; /* Allow mktime to determine DST setting. */
timeinfo.tm_mon = 0;
timeinfo.tm_mday = day;
timeinfo.tm_year = year - 1900;
loctime = mktime (&timeinfo);
loctimeinfo = localtime(&loctime);
printf ("The date for that day of the year is %s.\n", asctime(loctimeinfo));
return 0;
}
编译和示例运行:
$ g++ -o t2 t2.c
$ ./t2
Enter year: 2013
Enter day of the year: 1
The date for that day of the year is Tue Jan 1 00:00:00 2013
$ ./t2
Enter year: 2013
Enter day of the year: 365
The date for that day of the year is Tue Dec 31 00:00:00 2013
甚至适用于像 2012 年这样的闰年:
$ ./t2
Enter year: 2012
Enter day of the year: 366
The date for that day of the year is Mon Dec 31 00:00:00 2012