No.17836![]() |
通算日から日付を取得 投稿者---7(2004/11/07 00:16:02) |
||
こんばんは。今2004年の通算日が何月何日何曜日であるかという プログラムを作っています。 まず、int c[]={31,29,31,30,31,30,31,31,30,31,30,31};のように 各月の日数を配列に格納しておきます。 そして、通算日を取得し、表示するというものです。 曜日などはやり方は思いついているのですが、何日であるかを得る方法が うまくいきません。 私はscanfで int aを取得したとき、 a -= c[i]; i++; でaが0以上の時はループさせようとしました。 たとえば、通算日が32日であれば、2月1日(日)を得ることができる プログラムです。 |
No.17837![]() |
Re:通算日から日付を取得 投稿者---PSB(2004/11/07 00:42:26) |
||
>私はscanfで int aを取得したとき、 >a -= c[i]; >i++; >でaが0以上の時はループさせようとしました。 それでいいと思いますが。aが負の値になった後に直前に引いた値を 足せば月日は出ますよね。 |
No.17838![]() |
Re:通算日から日付を取得 投稿者---YuO(2004/11/07 01:07:26) |
||
>こんばんは。今2004年の通算日が何月何日何曜日であるかという >プログラムを作っています。 localtimeとmktime使えば簡単に取得できます。 const struct tm * yday_to_tm (int year, int yday) { struct tm tmYday = { 0 }; time_t timeYday; tmYday.tm_year = year - 1900; tmYday.tm_day = yday; timeYday = mktime(&tmYday); return localtime(&timeYday); } #夏時間を考慮していないので,場合によっては日付がずれるかも……。 |
No.17839![]() |
Re:通算日から日付を取得 投稿者---かずま(2004/11/07 02:00:34) |
||
> tmYday.tm_day = yday; tmYday.tm_mday = yday; の間違いでしょう。 |
No.17840![]() |
Re:通算日から日付を取得 投稿者---rvrdriver(2004/11/07 14:26:51) |
||
tm_ydayはmktimeの変換では無視されるので求めるとしたら、 1.tm構造体のメンバに2004年1月1日を設定 2.mktimeで2004年1月1日を暦時刻に変換 3.暦時刻に変換した値に通算秒(通算日を秒に変換)を 加算 4.localtimeで時刻を求める struct tm *yday_to_tm (int year, int yday) { struct tm tmYday = { 0 }; time_t timeYday; tmYday.tm_year = year - 1900; tmYday.tm_mon = 0; tmYday.tm_mday = 1; tmYday.tm_isdst = -1; timeYday = mktime(&tmYday); timeYday += (yday * 3600 * 24); return localtime(&timeYday); } 夏時間を考慮に入れたい場合はtm_isdstをセットする必要があります。 unixの場合は-1をセットするとmktimeで夏時間を考慮した暦時刻に 変換されますが他の環境ではわかりません。 また、3600や24のマジックナンバーは#defineしたほうがいいですね。 |
No.17841![]() |
Re:通算日から日付を取得 投稿者---nop(2004/11/07 15:49:48) |
||
>tm_ydayはmktimeの変換では無視されるので求めるとしたら、 tm_ydayではなくtm_mdayなので問題ないでしょう。 |
No.17842![]() |
Re:通算日から日付を取得 投稿者---rvrdriver(2004/11/07 16:35:00) |
||
>tm_ydayではなくtm_mdayなので問題ないでしょう。 JIS X 3010 7.23.2.3 mktime 関数には、 構造体のtm_wday 要素及びtm_yday 要素の元の値は無視 すると記載されていますし、実際YuOさんのコードを 実行しても求められませんでした。 RedhatLinux9、gcc WinXP、bcc 両方の環境で試しましたが求められませんでした。 nopさんはどのような環境で試されましたか? |
No.17843![]() |
Re:通算日から日付を取得 投稿者---nop(2004/11/07 17:15:17) |
||
>JIS X 3010 7.23.2.3 mktime 関数には、 >構造体のtm_wday 要素及びtm_yday 要素の元の値は無視 >すると記載されていますし、 「tm_wday」でも「tm_yday」でもなく「tm_mday」ですって…。 # tm_wday … 曜日 # tm_yday … 年初からの通算日数 # tm_mday … 日 # # 読み変えると # 「曜日」でも「年初からの通算日数」でもなく「日」 |
No.17845![]() |
Re:通算日から日付を取得 投稿者---rvrdriver(2004/11/07 17:47:36) |
||
>「tm_wday」でも「tm_yday」でもなく「tm_mday」ですって…。 この根拠となるものは何でしょうか? JIS X 3010(ANSI Cの日本語訳)よりもっと信頼性のある情報である としたら大変興味ありますので教えてください。 或いはmktimeの項の誤訳であるということでしょうか? また、先ほど質問しましたが動作確認はされてますか? > ># tm_wday … 曜日 ># tm_yday … 年初からの通算日数 ># tm_mday … 日 ># ># 読み変えると ># 「曜日」でも「年初からの通算日数」でもなく「日」 これはtm構造体の内容でmktimeの仕様を推定しているのでしょうか? 何を読み変えているのか良くわかりません。 質問ばっかりになってしまってすみません。 |
No.17846![]() |
Re:通算日から日付を取得 投稿者---かずま(2004/11/07 18:12:53) |
||
> この根拠となるものは何でしょうか? > JIS X 3010(ANSI Cの日本語訳)よりもっと信頼性のある情報である > としたら大変興味ありますので教えてください。 > 或いはmktimeの項の誤訳であるということでしょうか? JIS X 3010 の次の記述を読み落としていませんか? : 構造体の tm_wday要素及び tm_yday要素の元の値は無視し, : その他の要素の元の値は, 7.23.1 に示した値の範囲内でなくてもよい。 : 正常に動作が完了した場合, 構造体の tm_wday要素及び tm_yday要素の : 値を適切に設定し, 他の要素は指定された暦時刻を表すように設定するが, : それらの値は, 7.23.1 で示した範囲に強制的に設定する。 tm_mday は 1〜31 の範囲であるが、範囲外の 312 を指定して、 2004年 1月 312日を渡すと、2004年 11月 7日に強制的に設定されると いうことです。 |
No.17847![]() |
Re:通算日から日付を取得 投稿者---rvrdriver(2004/11/07 18:29:56) |
||
>tm_mday は 1〜31 の範囲であるが、範囲外の 312 を指定して、 >2004年 1月 312日を渡すと、2004年 11月 7日に強制的に設定されると >いうことです。 すみません。自分の見落とし&勘違いでした。 ご指摘のとおり、規格を見落としていました。 また、最初にコンパイルができず、tm_dayを勘違いして tm_ydayに書き換えていたのが原因でした。 皆さんがいっているとおりtm_mdayにすれば問題なく動作します。 いろいろお手数おかけしました。 |
No.17844![]() |
Re:通算日から日付を取得 投稿者---かずま(2004/11/07 17:38:46) |
||
> 実際YuOさんのコードを実行しても求められませんでした。 YuOさんのコードは、struct tm にはない tm_day と書いているので 実行できません。tm_mday の間違いです。localtime も不要です。 #include <stdio.h> #include <time.h> int main(void) { int yday; while (scanf("%d", &yday) == 1) { struct tm t = { 0 }; t.tm_year = 2004 - 1900; t.tm_mday = yday; mktime(&t); printf("%d/%02d/%02d(%.3s)\n", t.tm_year+1900, t.tm_mon+1, t.tm_mday, "SunMonTueWedThuFriSat" + t.tm_wday*3); } return 0; } |