ページ 1 / 1
時刻指定による繰り返し実行処理について
Posted: 2014年2月03日(月) 23:51
by glen
引数にHHMMSS形式で時刻を渡し、
その時刻がきたら処理実行を繰り返し実行する
スケジュール実行のようなプログラム作成を試みています。
2回目の実行以降は1回目の実行から
60*60*12(24時間)sleepで可能と思いますが(ズレは置いておいて)、
初回実行の際に現時刻から指定時刻(HHMMSS)までsleepする差分時間を
求めたいのですが、time()等で得られる現時刻(YYYYHHMMDD)から指定時刻(HHMMSS)
の差(秒)を取得する良い方法はないでしょうか?
difftime()はtime_t形式で時刻の差分が取れるとのことですが
指定時刻をtime_t形式にする必要があり、他の方法がないかと思った次第です。
すみませんがアドバイスお願い致します。
Re: 時刻指定による繰り返し実行処理について
Posted: 2014年2月04日(火) 00:03
by みけCAT
なぜ指定時刻をtime_t形式にしてはいけないのでしょうか?
mktime関数で日時の情報が入ったtm構造体からtime_t型のデータを生成できます。
Re: 時刻指定による繰り返し実行処理について
Posted: 2014年2月04日(火) 00:06
by みけCAT
glen さんが書きました:他の方法がないかと思った次第です。
UNIX時間と日時のデータを相互変換する関数を自作すれば、
time_t型の単位の環境依存を気にせずに済むので、いいと思います。
前に自分が作ったライブラリを置いておきます。
► スポイラーを表示
コード:
typedef struct {
int year;
int month;
int date;
int hour;
int minute;
int second;
} ut2date_date_t;
static const int monthDays[13]={
0,31,59,90,120,151,181,212,243,273,304,334,365
};
#define SECONDS_PER_DAY 86400
static long long getDays(int year) {
long long result;
if(year<0)return -getDays(-year)-366+365;
else if(year==0)return 0;
result=year*365;
result+=year/4;
result-=year/100;
result+=year/400;
return result;
}
static long long getDays2(int fromYear,int toYear) {
return getDays(toYear)-getDays(fromYear);
}
static int getLeapYearNum(int year) {
int result;
if(year<0)return -getLeapYearNum(-year)-1;
else if(year==0)return 0;
result=year/4;
result-=year/100;
result+=year/400;
return result;
}
static int getLeapYearNum2(int fromYear,int toYear) {
return getLeapYearNum(toYear)-getLeapYearNum(fromYear);
}
static int isLeapYear(int year) {
return (year%400==0 || (year%4==0 && year%100!=0));
}
long long date2ut(int year,int month,int date,
int hour,int minute,int second) {
long long result;
if(month<1 || month>12)return 0;
result=getDays2(1969,year-1);
result*=SECONDS_PER_DAY;
result+=monthDays[month-1]*SECONDS_PER_DAY;
if(isLeapYear(year)) {
if(month>=3)result+=SECONDS_PER_DAY;
}
result+=(date-1)*SECONDS_PER_DAY;
result+=hour*60*60;
result+=minute*60;
result+=second;
return result;
}
void ut2date(ut2date_date_t* result,long long unixTime) {
int i;
long long days;
int yearNum;
int amariDays;
int daySeconds;
int hoseiYear;
int is2_29;
if(!result)return;
if(unixTime>=0) {
days=unixTime/SECONDS_PER_DAY;
daySeconds=(int)(unixTime%SECONDS_PER_DAY);
yearNum=1970+(int)(days/365);
amariDays=(int)(days%365);
} else {
days=(-unixTime)/SECONDS_PER_DAY;
daySeconds=(int)(SECONDS_PER_DAY-((-unixTime)%SECONDS_PER_DAY));
if(daySeconds==SECONDS_PER_DAY) {
daySeconds=0;
} else days++;
yearNum=1970-(int)(days/365)-1;
amariDays=365-(int)(days%365);
}
amariDays-=getLeapYearNum2(1969,yearNum-1);
while(1) {
if((amariDays>=0 && amariDays<365) ||
(amariDays==365 && isLeapYear(yearNum)))break;
if(amariDays<0) {
hoseiYear=(-amariDays)/365+1;
amariDays+=hoseiYear*365;
amariDays+=getLeapYearNum(yearNum-1)-
getLeapYearNum(yearNum-hoseiYear-1);
yearNum-=hoseiYear;
} else if(amariDays>=365) {
hoseiYear=amariDays/365;
amariDays=amariDays%365;
amariDays-=getLeapYearNum(yearNum+hoseiYear-1)-
getLeapYearNum(yearNum-1);
yearNum+=hoseiYear;
} else break;
}
is2_29=0;
if(isLeapYear(yearNum) && amariDays>=59) {
if(amariDays==59)is2_29=1;
amariDays--;
}
for(i=1;i<=12;i++) {
if(amariDays>=monthDays[i-1] && amariDays<monthDays[i])break;
}
amariDays-=monthDays[i-1];
if(is2_29)amariDays++;
result->year=yearNum;
result->month=i;
result->date=amariDays+1;
result->hour=daySeconds/3600;
result->minute=(daySeconds/60)%60;
result->second=daySeconds%60;
}
Re: 時刻指定による繰り返し実行処理について
Posted: 2014年2月04日(火) 00:25
by glen
回答ありがとうございます。
時刻情報(HHMMSS)に、日付情報等を付与して比較することに抵抗がありました。
日を跨ぐケースがある以上仕方ない事として理解しました。
本当はスケジュール実行できるような標準関数が用意されていれば
よいのですが、やはりsleep系でタイミングを取るしかないですかね。
Re: 時刻指定による繰り返し実行処理について
Posted: 2014年2月04日(火) 00:44
by みけCAT
glen さんが書きました:時刻情報(HHMMSS)に、日付情報等を付与して比較することに抵抗がありました。
日を跨ぐケースがある以上仕方ない事として理解しました。
次にx時y分z秒になるまでの時間を求めるだけなら、UNIX時間を使った複雑な計算をしなくても、
素直に計算すれば求められると思います。
glen さんが書きました:本当はスケジュール実行できるような標準関数が用意されていれば
よいのですが、やはりsleep系でタイミングを取るしかないですかね。
どの程度の精度が必要かにもよりますが、例えば1秒ずつsleepしつつ、現在時刻をチェックして、
「前回チェックした時に指定した時刻を越えていない」かつ「今回チェックした時に指定した時刻を越えている」ならば、
スケジュール実行したい処理を実行し、次に実行する時刻を1日後にずらす、という方法があります。
Re: 時刻指定による繰り返し実行処理について
Posted: 2014年2月04日(火) 00:51
by みけCAT
Re: 時刻指定による繰り返し実行処理について
Posted: 2014年2月04日(火) 01:41
by glen
ありがとうございます。
時刻計算についてのご指摘はごもっともです申し訳ありません。
#このような箇所であまりstep数を増やしたくないという思いもありまして..
エラーが発生しない限り実行し続けるプログラムであるため、
少しずつだとしてもズレが発生しないようにはしたいところです。
時刻とsleep時間の整合性確認についても
1日単位での処理実行を目的としているため、確認頻度は抑えられるので
性能への影響もほとんどなく済みますので問題なさそうですね。
加えてループスレッドの終了処理も検討して実装してみます。