私は2つの関数を使ってCでコードを書いています。Cの2つの日付間の勤務日数を計算する
最初の数字(WorkDay
)は、それが稼働日(return 1
)かどうか(return 0
)であるかどうかを日付で示します。最初の機能はOKだと思いますが、それは良いかもしれませんが、機能しています。私の国には週末や祝日が含まれています。
問題には2つ目の機能(CountWorkDays
)が付いています。 2つの日付が必要で、正しい場合は(return 1
)、その場合は、入力された日付(cnt=
)を含め、その中にいくつの就業日があるかを指定する必要があります。日付が正しくない場合(最初は2番目のものなど)、return 0
があります。私は助けの機能をnext_day()
にしようとしましたが、間違っていると確信しています。第二の機能で私を助けてくれますか? 私は<time.h>
を使用することはできませんし、いくつかのアサートを置いています。
#include <stdio.h>
#include <math.h>
#include <assert.h>
int WorkDay (int y, int m, int d)
{
int h, day;
h= (d + floor(((m+1)*26)/10) + y + floor(y/4) + 6*floor(y/100) + floor(y/400));
day=h%7;
if ((y%4!=0) && m==2 && d==29)
return 0;
else if (((y%4==0 || y%400==0) && (y%100!=0 || y%4000!=0)) && m==2 && d==29)
{
if (day==2 || day==3 || day==4 || day==1 || day==0)
return 1;
else
return 0;
}
else if ((d==1 && m==1) || (d==1 && m==5) || (d==8 && m==5) || (d==5 && m==7) || (d==6 && m==7) || (d==28 && m==9) || (d==28 && m==10) || (d==17 && m==11) || (d==24 && m==12) || (d==25 && m==12) || (d==26 && m==12) || day==0 || day==1 || (m==1 && (d>31 || d<1)) || (m==2 && (d>29 || d<1)) || (m==3 && (d>31 || d<1)) || (m==4 && (d>30 || d<1)) || (m==5 && (d>31 || d<1)) || (m==6 && (d>30 || d<1)) || (m==7 && (d>31 || d<1)) || (m==8 && (d>31 || d<1)) || (m==9 && (d>30 || d<1)) || (m==10 && (d>31 || d<1)) || (m==11 && (d>30 || d<1)) || (m==12 && (d>31 || d<1)) || y<2000 || m>12 || m<1)
return 0;
else if (day==2 || day==3 || day==4 || day==5 || day==6)
return 1;
else
return 0;
}
int next_day()
{
int y1, m1, d1;
static int days_in_month[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
unsigned short day_counter;
d1 += 1; day_counter++;
if (d1 > days_in_month[m1])
{
d1 = 1;
m1 += 1;
if (m1 > 12)
{
m1 = 1;
y1 += 1;
if (((y1%4==0 || y1%400==0) && (y1%100!=0 || y1%4000!=0)))
{
days_in_month[2] = 29;
}
else
{
days_in_month[2] = 28;
}
}
}
return 0;
}
int CountWorkDays (int y1, int m1, int d1,
int y2, int m2, int d2,
int * cnt)
{
int i,x;
if ((m1==1 && (d1>31 || d1<1)) || (m1==2 && (d1>29 || d1<1)) || (m1==3 && (d1>31 || d1<1)) || (m1==4 && (d1>30 || d1<1)) || (m1==5 && (d1>31 || d1<1)) || (m1==6 && (d1>30 || d1<1)) || (m1==7 && (d1>31 || d1<1)) || (m1==8 && (d1>31 || d1<1)) || (m1==9 && (d1>30 || d1<1)) || (m1==10 && (d1>31 || d1<1)) || (m1==11 && (d1>30 || d1<1)) || (m1==12 && (d1>31 || d1<1)) || y1<2000 || m1>12 || m1<1 ||(m2==1 && (d2>31 || d2<1)) || (m2==2 && (d2>29 || d2<1)) || (m2==3 && (d2>31 || d2<1)) || (m2==4 && (d2>30 || d2<1)) || (m2==5 && (d2>31 || d2<1)) || (m2==6 && (d2>30 || d2<1)) || (m2==7 && (d2>31 || d2<1)) || (m2==8 && (d2>31 || d2<1)) || (m2==9 && (d2>30 || d2<1)) || (m2==10 && (d2>31 || d2<1)) || (m2==11 && (d2>30 || d2<1)) || (m2==12 && (d2>31 || d2<1)) || y2<2000 || m2>12 || m2<1 || y2>y1 || (y1==y2 && m2>m1) || (y1==y2 && m1==m2 && d2>d1))
return 0;
else
{
while (y1!=y2 && m1!=m2 && d1!=d2)
{
while (next_day())
{
if (WorkDay(y1, m1, d1) == 1)
i=0;
x=i++;
}
}
*cnt=x;
return 1;
}
}
int main (int argc, char * argv [])
{
int cnt;
assert (WorkDay (2016, 11, 11));
assert (! WorkDay (2016, 11, 12));
assert (CountWorkDays (2016, 11, 1,
2016, 11, 30, &cnt) == 1
&& cnt == 21);
assert (CountWorkDays (2001, 1, 1,
2015, 2, 29, &cnt) == 0);
return 0;
}
以前のZellerの一致の変種を見たことがありません:元のものよりずっと簡単です。フロア((m + 1)* 26)/ 10)ビットの丸め誤差を監視します。私は多くの32ビットマシン実装に.0001を追加しなければならなかった。 – cup
土曜日の代わりに日曜日か月曜日のいずれかを0にするには、数式に1または2を追加することをお勧めします。 – cup