中小企業の働き方改革をサポート>>

2007,7,5,4
年,月,日,曜日(0が日曜日)
の入力から、+10日後の日付と曜日を求めたいのですが、
関数を一切使わず計算式と場合分けのみで計算する方法ありますか?

今考えている方法は、地道に、ある基準1970年1月1日をシリアル値で0としそこから、今日までの日数を1月は31、2月は28にちなどを考えてを足していき、シリアル値を算出。
そのシリアル値に+10した値を再び年月日曜日の形に戻す方法しか無いのかと考えています。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

★最初に


>関数を一切使わず計算式と場合分けのみで計算する方法ありますか?
 ↑
 あります。というか関数で記述することを記述すればよいだけ。
 汎用性も考えれば専用の関数か、日付操作ライブラリを自作して使いまわした方が
 良いと思いますよ。
>今考えている方法は、地道に、ある基準1970年1月1日をシリアル値で0としそこから、
>今日までの日数を1月は31、2月は28にちなどを考えてを足していき、シリアル値を算出。
>そのシリアル値に+10した値を再び年月日曜日の形に戻す方法しか無いのかと考えています。
 ↑
 私もこの方法しか思い浮かびません。
 このときの注意点として『閏年』の判定、扱いをきちんと考えないと正確になりません。
 表計算で有名な Excel について興味深い記事を見つけましたので読んで見て下さい。
 http://pc.nikkeibp.co.jp/article/NPC/20070530/27 …→『DATEDIF関数の“受難” (第1回)』
 ↑
 3ページ目です。
>10日ではなくて10000日だったらどんな感じになりますか?
 ↑
 加減算する日付を西暦1年1月1日を1としたシリアル値に変換して加算、減算とするしかないかな。
・開始日を Y1/M1/D1 とすると
 days = ((Y1 * 365) + (Y1 / 4) - (Y1 / 400 * 3)) + FuncGetDays(Y1,M1,D1);
 days += 10000; ←加算
 days -= 10000; ←減算
 この days のシリアル値を年、月、日に変換します。
 ※FuncGetDays() 関数は年月日から1月1日の日数を計算する関数です。
 ※この関数の詳しい内容は下の『参考URL』をどうぞ。回答者No.2です。
 ※そのたも参考になります。
・以上。

参考URL:http://oshiete1.goo.ne.jp/qa3085731.html
    • good
    • 1
この回答へのお礼

いや~、参考になりました。ありがとうございました。

お礼日時:2007/07/05 13:56

10000日でも処理方法は変わりません。



1)単純に「日」に 10000を足す
2)その「日」の結果は、「月」に対して妥当か? 
  妥当ならそれが答
3)「日」から、その月の日数を引く
  「月」をひとつ増やす
4)その「月」は妥当か? 
  妥当ならそれが答
5)月を1にして、年をひとつ増やす
7)2に戻る
8)終わり。
    • good
    • 0

曜日が入力されるのであれば、曜日の処理は簡単ですね。


(そもそも、入力値は7種類しかない)

日付は

1)単純に「日」に 10を足す
2)その「日」の結果は、「月」に対して妥当か?
  (ここで、「その月は何日あるか」がわかっている*はず*であることに注意)
  妥当ならそれが答

3)「日」から、その月の日数を引く
  「月」をひとつ増やす
4)その「月」は妥当か? 妥当ならそれが答

5)月を1にして、年をひとつ増やす

6)終わり。

この回答への補足

ありがとうございます。曜日は簡単ですね。

2月25日の場合、年によってうるう年かどうか判定すればよいってことですね。

10日ではなくて10000日だったらどんな感じになりますか?

補足日時:2007/07/05 11:46
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q簡素で美しく記述するには・・・・

今与えられた開始日から与えられた終了日までの期間を求めるプログラムを作りました。勿論その中で閏年の計算も行います。
自分の作ったプログラムでは1つだけ気に入らないところがありました。それは閏年の計算部分です。


■うるう年の判定
・年が4で割り切れる時はうるう年
 従って、2004年はうるう年である
・ただし、100で割り切れる時はうるう年でない
 従って、1900年はうるう年ではない
・ただし、400で割り切れる時はうるう年である。
 従って、2000年はうるう年である



この条件を行うため自分は次のように記述しました

for(year = First_Year; year <= End_Year; year++){
  if(((year  % 4) == 0) && ((((year % 100) != 0) && ((year % 400) != 0)) || (((year % 100) == 0) && ((year % 400) == 0)))){
    閏年の個数を数える
   }
}

for文変数の初期でFirst_Yearを与えていますが、First_Yearが開始年でEnd_Yearが終了年です。
if文がむかつくほど長くなってしまいました。やっていることはyearが4で割り切れかつ100と400で割ったときに両方共に余りが出る、またはyearが4で割り切れかつ100と400で割ったときに両方共に余りが出ない場合に 閏年の個数を数える ようにしています。


かなり強引な質問ではありますが、みなさんならどのように組むでしょうか? 別に自分の考える”美しい”プログラムでなくてもかまいません。色々な考えを聞かせてもらえないでしょうか?

今与えられた開始日から与えられた終了日までの期間を求めるプログラムを作りました。勿論その中で閏年の計算も行います。
自分の作ったプログラムでは1つだけ気に入らないところがありました。それは閏年の計算部分です。


■うるう年の判定
・年が4で割り切れる時はうるう年
 従って、2004年はうるう年である
・ただし、100で割り切れる時はうるう年でない
 従って、1900年はうるう年ではない
・ただし、400で割り切れる時はうるう年である。
 従って、2000年はうるう年である



この...続きを読む

Aベストアンサー

プログラムを簡素で美しく記述する王道は、
・何をするのかを日本語で簡潔にまとめる(整理する)
→ うるう年判定であれば、判定方法を整理します。
  (1)4で割れる年をうるう年とする
  (2)100で割れる年は平年にする
  (3)400で割れる年はうるう年とする
・凝ったことをしようとしない。
→ ビット操作とかポインタ操作とかできるのがCの醍醐味ですが、いわゆる「テクニック」を使わないほうが実は簡素で美しくなる傾向にあります。

これを心がけてうるう年判定関数を作ってみました。
bool is_leap(int year){
  if(year % 400 == 0) return true;
  if(year % 100 == 0) return false;
  if(year % 4 == 0) return true;
  return false;
}
書き方によっては実行速度がはやい方法もあるでしょうけど、うるう年関数なんかチューニングするより、他のアーキテクチャを見直したほうがよっぽど効果的です。

また、この関数であれば、3200年に一度うるう年でないことに対応
させたい(いわゆる仕様追加みたいな場面)ときに
  if(year % 3200 == 0) return false;
を追加すればよいことが一目瞭然です。
複雑な条件式を書かずに素直に書くと、メンテが楽になりますね。

プログラムを簡素で美しく記述する王道は、
・何をするのかを日本語で簡潔にまとめる(整理する)
→ うるう年判定であれば、判定方法を整理します。
  (1)4で割れる年をうるう年とする
  (2)100で割れる年は平年にする
  (3)400で割れる年はうるう年とする
・凝ったことをしようとしない。
→ ビット操作とかポインタ操作とかできるのがCの醍醐味ですが、いわゆる「テクニック」を使わないほうが実は簡素で美しくなる傾向にあります。

これを心がけてうるう年判定関数を作ってみました。...続きを読む

QC言語でシステム日付との差を求める

いつもお世話になっております。
C言語で以下のような処理を実現したいと思っているのですが
可能でしょうか。

「20091020」のような8桁の日付が文字列として格納されている
変数に対して、システム日付からどれくらい差があるか。

【例】
(1)システム日付が2009/10/19
(2)チェックしたい8桁の文字列="20091025"
(3)上記(1)、(2)を利用して、差が10~20の間の場合はNG!

といったことを実現したいです。

Aベストアンサー

お疲れ様です。
C言語で標準で規定されている関数のみで作成すると以下の通りになると思います。
(2038年問題等がありますが。。。)

#include<stdio.h>
#include<time.h>

int main()
{
time_t now,dat;
char *timedat = "20091030";
struct tm ts = {0};
double diff,nissuu;

/* 現在時刻の取得 */
now = time(NULL);

/* 日付をtime_tに変換 */
sscanf(timedat ,"%4d%2d%2d",&(ts.tm_year),&(ts.tm_mon),&(ts.tm_mday));
ts.tm_year -= 1900;
ts.tm_mon -= 1;
dat = mktime(&ts);

/* 差分算出 */
diff = difftime(dat, now);
nissuu = diff / (60*60*24);

}

お疲れ様です。
C言語で標準で規定されている関数のみで作成すると以下の通りになると思います。
(2038年問題等がありますが。。。)

#include<stdio.h>
#include<time.h>

int main()
{
time_t now,dat;
char *timedat = "20091030";
struct tm ts = {0};
double diff,nissuu;

/* 現在時刻の取得 */
now = time(NULL);

/* 日付をtime_tに変換 */
sscanf(timedat ,"%4d%2d%2d",&(ts.tm_year),&(ts.tm_mon),&(ts.tm_mday));
ts.tm_year -= 19...続きを読む

Q日付の差分の求め方(日、分)

NT4WS+VC++6.0 Win32コンソールアプリで作ってます。
現在int型で
year1,month1,day1 year2,month2,day2
の様に、1と2それぞれ年月日を持っています。
(year2/month2/day2) - (year1/month1/day1)
と言った感じで1と2の差が何日かを求めたいのです。
VBで言うDateDiffみたいなことがやりたいのです。
よろしくお願いします。

Aベストアンサー

ANSI の範囲で考えると、difftime() という関数が利用できます。difftime() が
扱えるのは time_t 型で表した時刻なのですが、整数で表された年月日などを、この
time_t 型に変換する mktime() という関数と組合わせて使います。

こういうふうに使います。

#include <time.h>
#include <stdio.h>

int main()
{
  int year1, month1, day1;
  int year2, month2, day2;
  year1 = 2001; month1 = 12; day1 = 30;
  year2 = 2002; month2 = 1; day2 = 16;

  {
    struct tm d;
    time_t t1, t2;
    double diff;

    // 開始・終了日を time_t 型の変数にする
    memset(&d, 0, sizeof(d));
    d.tm_year = year1 - 1900;
    d.tm_mon = month1 - 1;
    d.tm_mday = day1;
    t1 = mktime(&d);
    d.tm_year = year2 - 1900;
    d.tm_mon = month2 - 1;
    d.tm_mday = day2;
    t2 = mktime(&d);

    diff = difftime(t2, t1);

    // difftime() の返り値は「秒」で double 型
    // ÷60÷60÷24 で日数にして、+0.5 は四捨五入のため
    printf("%d 日差.\n", (int)(diff / 60 / 60 / 24 + 0.5));
  }

  return 0;
}

ANSI の範囲で考えると、difftime() という関数が利用できます。difftime() が
扱えるのは time_t 型で表した時刻なのですが、整数で表された年月日などを、この
time_t 型に変換する mktime() という関数と組合わせて使います。

こういうふうに使います。

#include <time.h>
#include <stdio.h>

int main()
{
  int year1, month1, day1;
  int year2, month2, day2;
  year1 = 2001; month1 = 12; day1 = 30;
  year2 = 2002; month2 = 1; day2 = 16;

  {
    struct tm d;
...続きを読む

Q2038年問題 日付算出

2038年問題で困っています。
指定した日付から指定した日数後および前(マイナス日数)の日付を取得するCのプログラムがあります。
これまでmktime関数をして算出していましたが、2038年以降の日付を指定するとエラーになるようです。
上記関数をmktime関数を使用せず自前で作成しないといけないのですが、どう作っていいか思いつきません。どなたか参考になるようなサイト、およびサンプルプログラムがあれば教えていただきたいと思っています。
よろしくお願いします。

Aベストアンサー

★アドバイス
・一般的に次の方法を取ります。
 (1)年月日を西暦1年1月1日からの経過日数に変換
 (2)経過日数に(期間の)日数を加算/減算
 (3)西暦1年1月1日からの経過日数を年月日に変換
 このうち(3)が最も面倒な作業になります。多分。
 下に(3)だけですがサンプルを載せておきます。

サンプル:
// 閏年の判定
int isLeapYear( int year )
{
 if ( !(year % 3200) ) return 0;
 if ( !(year % 400) ) return 1;
 if ( !(year % 100) ) return 0;
 return !(year & 0x3);
}

// 経過日数から年月日を求める
int sample3( int days, int *year, int *month, int *day )
{
 static int table[ 13 ] = {
  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
 }; int Y, M, D, ddd;
 
 // [日]コピー
 D = days;
 // [年]算出
 for ( Y = 1 ; D > (ddd = (isLeapYear(Y) ? 366 : 365)) ; Y++ ){
  D -= ddd;
 }
 // [月]算出
 table[ 2 ] = ((ddd == 365) ? 28 : 29);
 for ( M = 1 ; D > table[M] ; M++ ){
  D -= table[ M ];
 }
 // セット
 *year = Y;
 *month = M;
 *day = D;
 return days % 7; // 曜日を返す(0-6)
}

その他:
・上記のソースは『経過日数を年月日に変換』する考え方のサンプルです。
 そのため計算スピードが低速で実用にはなりません。
 その代わりに正しく変換してくれます。
 答え合わせようの関数です。
・実際に利用するためには『年の算出』を除算と剰余を使って計算させます。
 考え方は
 (1)経過日数から3200年間の日数(1168776日)を幾つ引けるかを除算で求める。
 (2)(1)のあまりの経過日数から400年間の日数(146097日)を幾つ引けるかを除算で求める。
 (3)(2)のあまりの経過日数から100年間の日数(36524日)を幾つ引けるかを除算で求める。
 (4)(3)のあまりの経過日数から4年間の日数(1461日)を幾つ引けるかを除算で求める。
 (5)(4)のあまりの経過日数から1年間の日数(365日)を幾つ引けるかを除算で求める。
 (6)(1)-(5)までで求めた除算の商と年数を掛けて加算すると『年』が求まる。
 (7)(5)のあまりが年内の1月1日からの通算日数となります。これを『月』『日』に分ける。
・詳しい解説などは下の『参考URL』をどうぞ。
 そこで紹介している『経過日数から年月日と曜日を求める』なら実用的なスピードで
 計算してくれます。ただし有効範囲は3199年までです。3200年以降は1日ずつずれます。
 これは3200年以降の閏年を考慮していないためです。でも誤差1日ですが。
・以上。

参考URL:http://cl.is.kyushu-u.ac.jp/Literacy/PP/H14/adp/program/date.html

★アドバイス
・一般的に次の方法を取ります。
 (1)年月日を西暦1年1月1日からの経過日数に変換
 (2)経過日数に(期間の)日数を加算/減算
 (3)西暦1年1月1日からの経過日数を年月日に変換
 このうち(3)が最も面倒な作業になります。多分。
 下に(3)だけですがサンプルを載せておきます。

サンプル:
// 閏年の判定
int isLeapYear( int year )
{
 if ( !(year % 3200) ) return 0;
 if ( !(year % 400) ) return 1;
 if ( !(year % 100) ) return 0;
 return !(year & 0x3);
}

// 経...続きを読む

QC言語を使って、ある特定の日の前日を求めたい

プログラミングを初めて約2か月の初心者です。

C言語を使って、int型で表示されたある日付から、一日分差し引いた日付を求めたいのですが。
(例えば、2008年7月31日を求めたいなら、
20080801 から、一日分差し引い、20080731 にする。)

どうしたらいいのか全く分からない状態なので、
なにかとっかかりになるものだけでもいいので、教えていただけないでしょうか。
よろしくおねがいします。

Aベストアンサー

ずっと昔やずっと未来の年を扱うのでなければ、

int date = 20080801;
struct tm t = { 0 };
t.tm_year = -1900 + date / 10000;
t.tm_mon = -1 + date / 100 % 100;
t.tm_mday = date % 100 - 1;
mktime(&t);

とすれば、tに正しい年月日が格納されます。

Qfgetsで拾われる改行文字を削除したい

お世話になります

 C言語初心者のものです。今課題でC言語を用いたプログラミングを
Fedora上でやっています。問題は、fgetsでテキストファイルから、取得
した文字列の中から改行文字を削除できないことです。文字変数のアド
レスはわかっているのですが、終端文字に置換しようとすると、セグメ
ントエラーになってしまいます。これは如何にして解決すべきでしょう
か。よろしくお願いします。

Aベストアンサー

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが最大文字数に達したり、ファイルの最後になったりで、strに改行文字が含まれない場合には、このループは止まりません(Segmentension Falutになって止まる)

・そのような状態になってないか、予めチェックする
・ループを終了させる仕組みを用意しておく
: forの終了条件を記述する、for中で if(*(str+i)=='\0') { break;} 等としておく、等
といった対策が必要です。


あと細かいところを言えば
・strを配列で用意したなら *(s+i)じゃなくてs[i]でいいんじゃないかな
・あるいは char *pみたいにしておいて、 iのループでなく pでループを組む( for(p=str;*p!='\0';p++) )とか。

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが...続きを読む

Qセグメンテーション違反

C言語を使用しています。

構造体に値をいれようとしたら、コンパイルは出来るのですが、実行時に
「セグメンテーション違反です (core dumped)」
となってしまい、それ以上行えません。

構造体と代入したい変数との型は、合っています。

いろいろ本などで見ましたが、何が原因かわからず困っています。
教えてください。
宜しくお願いします。

Aベストアンサー

OSは何でしょうか。コンパイラは何を使用していますか?
通常、デバッグオプションをつけて実行すると、異常の発生したソースの箇所で止まりますので、それが手がかりになります。またNo1の方が言われてますように、ソースが公開できるのであれば、ソースを提示するのが良いかと思います。

Q日数を計算する方法

以下のようにして変数の配列を使って、
月の日数を格納しています。
int mon[12]={31,28,31,30,31,30,31,31,30,31,30,31};

これを使って、
元旦から入力された月日の日数を計算したいのですが
どの様にすればいいですか?

例えば、

4月5日の場合は、
1月 31日
2月 28日
3月 31日
4月 5日

なので「95日」

----------------
途中までのプログラム
#include<stdio.h>

main(void)
{int yy, mm, dd;
int mon[12]={31,28,31,30,31,30,31,31,30,31,30,31};

printf( "西暦を入力しなさい" );
scanf( "%d", &yy );
printf( "月を入力しなさい" );
scanf( "%d", &mm );
printf( "日を入力しなさい" );
scanf( "%d", &dd );

/* うるう年判定 */
if (((yy%4==0)&&(yy%100!=0))||(yy%400==0)) mon[1]=29; else mon[1]=28;

以下のようにして変数の配列を使って、
月の日数を格納しています。
int mon[12]={31,28,31,30,31,30,31,31,30,31,30,31};

これを使って、
元旦から入力された月日の日数を計算したいのですが
どの様にすればいいですか?

例えば、

4月5日の場合は、
1月 31日
2月 28日
3月 31日
4月 5日

なので「95日」

----------------
途中までのプログラム
#include<stdio.h>

main(void)
{int yy, mm, dd;
int mon[12]={31,28,31,30,31,30,31,31,30,31,30,...続きを読む

Aベストアンサー

要するに「配列にあるデータの合計を求める」のと同じなんだから, ふつうに考えれば for 文で足し込んでいくんでしょ~ね.

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。

QC言語 ミリ秒を日付に変換には

初心者です orz
ただいまC言語勉強中です。(仕事で必要になりそう・・・)

やりたいことは、タイトルの通り
「C言語 ミリ秒を日付に変換」です。
1298616934703→yyyyMMddhhmmddssSSS
↑こういう感じのことがしたいです!

ログにミリ秒で吐き出された時間から日付を求めたいのですが、
やり方が、いまいちわかりません(泣)

どなたか参考サイトや変換方法をご教授願えると助かります。

Aベストアンサー

その「ミリ秒で吐き出された時間」という数値が、
単純にエポック秒を1000倍したものだったら、
1000で割った商と余りでに「秒単位の数値(エポック秒)」と「ミリ秒部分」に分けてから、
エポック秒を年月日時分秒に変換するだけでしょう。

---ここから---
#include <stdio.h>
#include <time.h>

void conv_time(char *dst, long long t)
{
time_t clock = t / 1000LL;
int millisec = t % 1000LL;
struct tm *local = localtime(&clock);
sprintf(dst, "%04d%02d%02d%02d%02d%02d%03d",
local->tm_year + 1900,
local->tm_mon+1,
local->tm_mday,
local->tm_hour,
local->tm_min,
local->tm_sec,
millisec);
}


int main(int argc, char *argv[])
{
long long t = 1298616934703LL;
char s[18];
conv_time(s, t);
printf("%lld -> %s\n", t, s);
}
---ここまで---

その「ミリ秒で吐き出された時間」という数値が、
単純にエポック秒を1000倍したものだったら、
1000で割った商と余りでに「秒単位の数値(エポック秒)」と「ミリ秒部分」に分けてから、
エポック秒を年月日時分秒に変換するだけでしょう。

---ここから---
#include <stdio.h>
#include <time.h>

void conv_time(char *dst, long long t)
{
time_t clock = t / 1000LL;
int millisec = t % 1000LL;
struct tm *local = localtime(&clock);
sprintf(dst, "%04d%02d%02d%02d%02d%02d%03d",
local->tm_year + 1900,
...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング

おすすめ情報