最も移植性が高く信頼性の高い方法は、C または C++ で動作する ANSI C mktime および localtime 関数を使用することです。
アップデート:
標準 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;
};
仕事をするかもしれないサンプルコードを示すために、私が反対票を投じられないことを願っています. もちろん、必要に応じて自由に実装してください。これはアプローチの一例にすぎません。
プログラミングしているプラットフォームの標準Cライブラリに存在する可能性が最も高い既存のmktime機能(推奨)を使用したい場合は、私の元の回答内容が続きます...
mktime を使用する場合は、tm_mon=0 と tm_mday を必ずその年の日付に設定する必要があります (より詳しい説明については、mktime のドキュメントを参照してください)。 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