どなたか、任意の日付xから、n営業日前の日付yを簡単に求めるスクリプトご存知じゃないですか?

モジュールでも結構です。
Time:Localもつかって結構です。

休日は土・日で、祭日は無視して結構です。
アルゴリズムだけでも結構です。

金曜日から5営業日前だったら金曜ですが、3営業日前だと火曜日ですよね。
また数十日前となると、7で割って、それに2掛けて日数を足してそれを金曜日の日付からひいて。。。。と悩んでると、片頭痛が再発しそうです。

よろしくお願いします。

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

A 回答 (2件)

質問文にある変数、x, n, y を、それぞれ変数 $x, $n, $y として使用します。


また、$x, $y は、シリアル秒とします。

$w = (localtime($x))[6];
if ($n >= $w) {
  $s = int(($n - $w) / 5) + 1;
  $n += $s * 2;
}
$y = $x - $n * (60*60*24);

(多分)これで求まると思います。

■考え方
・n 営業日前、というのが、1回も土日をまたがなければ、$x から $n 日分のシリアル秒を引けばOKです。
・1回でも土日をまたぐのであれば、前週の金曜日まで(営業日で)戻り、そこから(週5日で)何週分あるかを求めます($s)。その週数に土日の日数(2)をかけた値を $n に足せば、土日を含めて何日前かが求まります。
    • good
    • 0
この回答へのお礼

ありがとうございます。
すごいです。

考え方を読むと、ごもっとも、かつシンプル。
ほんとにありがとうございます
いただきます。

お礼日時:2002/03/22 01:17

演習問題のつもりで挑戦した初心者回答の失礼をご容赦ください。


実行未確認の「力ずく」ですが・・・

$theday = timelocal(0, 0, 0, dd, mm-1, yyyy); #日付 x のシリアル秒
$i = 0; #経過営業日を0からスタート
while ($i < $n) { #経過営業日が n に達したら抜ける
$theday = $theday - 24*60*60; #1日前のシリアル秒
$wday = (localtime($theday))[6]; #その曜日を求めて
if (($wday != 0) && ($wday != 6)) { #土日でなければ
++$i;} #経過営業日を加算して
} #戻る
$y = localtime($theday); #経過営業日数が n に達した日付を得る
    • good
    • 0
この回答へのお礼

早速ありがとうございます。

そうなんですよね。
ループの度にlocaltimeを呼び出すのがヤで最後の手段にとは思ってるんですが、案外他に手は無いのかも知れないですね。

日付の計算ってほんとややこしいですよね。

お礼日時:2002/03/20 02:36

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

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

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

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

Q指定した日付から曜日を求める。

localtimeを使うと今現在の曜日や時間、日付がわかりますよね?
そうではなく、たとえば、2003/09/12という指定をしたときに、金曜と返ってくるようにするにはどのようにしたらいいのでしょうか?

Aベストアンサー

こちらのサイトを参考にしてみては如何でしょうか?
年月日の要素入力はご自身のプログラムにあわせてください。

参考URL:http://www.din.or.jp/~ohzaki/perl.htm#Date2WDay

QPerlで環境変数を設定するには

あるPathを環境変数として設定したい場合、
例)TNS_ADMIN=D:\Test\exe

たとえばMS-DOSなら、
set TNS_ADMIN=D:\Test\exe
と設定しますよね。

これと同じことをPerlでどうやればいいのかというのが質問です。

ENVモジュールを使って、
$ENV{TNS_ADMIN}=D:\Test\exe
としてみたものの、Perlを実行した後に確認してみるとセットされていないようでした。
(確認方法はPerlを実行したDOSプロンプトにて"set"を実行)

よろしくお願いします。

Aベストアンサー

>>破棄された後に確認しても、わかりません。
>どうにかその環境変数がセットされていることを確認する方法ってないのでしょうか?

perlで子プロセスを起動すれば確認できます。

例えば、NT系のOSであれば...

次のスクリプトを用意。
#!c:\perl\bin\perl.exe
$ENV{"TNS_ADMIN"}="D:\\Test\\exe";
system("cmd");

それを実行すると、コマンドプロセッサが表示されるので、
set[return]
すれば、子プロセスの環境変数が確認できます。
確認後、exit[return]すると、子プロセスが終了するので、
親プロセスたるperlも終了する。

Q日付の比較について

いつもお世話になります。
ファイルに記述された日付に7日を加算した値とlocationtimeで取得した値を比較したいのですが、記述方法が分かりません。
<ファイルは下記のようになっております。>
2006<>03<>28<>明細
これに7を加算した(7日後という意味です)locationtimeでreturn "$year/$mon/$day";の戻り値と比較した比較したいのですが、
どのようにしたらよいのでしょうか?
どなたかご教示お願いいたします。

Aベストアンサー

# あ、こういうことですか?
# まだ違ってたりして・・

use strict;

my $date1='20060328';
my $date2='2006/04/05';
$date2=~ s{\/}{}g;

if($date1 <= $date2){
print '$date1 <= $date2';
}else{
print 'else';
}

Qひとつの命令を複数行に記述

検索してもあまり解説見かけないなぁと思うのですが、(どこが本家かわからないのでとりあえず放置)

VBでいう_に該当するものは何ですか?
ソースが長くなって見にくくなっているので、対処したいのですが。

hoge = "じゅげむじゅげむごごうのすりきれ" _ '←次の行に送る
& "かいじゃりすいぎょのうんらいまつふうらいまつすいぎょうまつ" 

Aベストアンサー

Perlは、VBと異なり行の概念がありません。
VBではステートメント区切り子が存在しないため、改行がステートメントの区切りとして扱われ、例外的につなげるときに「_」を使うわけですが、
Perlの場合はステートメント区切り子セミコロン「;」がステートメントの区切りになっていますので、セミコロンを打たない限り、何行に分かれてもひとつのステートメントとして扱われます。
したがって、回答としては「そのまま改行してOK」です。
上記の例なら、

$hoge = "じゅげむじゅげむごごうのすりきれ" .
"かいじゃりすいぎょのうんらいまつふうらいまつすいぎょうまつ";

という感じです。
当然ながら、文字列中での改行はダメなので、上記のようにいったん「"」を閉じて、文字列結合演算子「.」で接続することに成ります。

Q10営業日前の日付を取得したい(修正)

※連投すみません。削除も修正もできなかったので連投になってしまいました。
一番重要な説明をコピペミスしてしまいました。
明日になれば削除できるようなので古い方は明日削除致しますm(__)m

---ここから---
今日は9/24という想定で各部署の10営業日前の日付を取得したいのですが良い方法が思いつきません。
(ここ↓を参考にしたらできそうな気がしましたが私の頭では無理でした。。。)
http://oshiete.goo.ne.jp/qa/6677209.html

【休日テーブル】
部署コード, 休日
-----------------
busyo1,   9/13
busyo1,   9/14
busyo1,   9/20
busyo1,   9/21
busyo1,   9/23
busyo2,   9/7
busyo2,   9/14
busyo2,   9/21
busyo3,   9/20


【結果】(各部署の10営業日前の日付)
部署コード, 日付
-----------------
busyo1,   9/9
busyo2,   9/12
busyo3,   9/13


このような「発想の転換」が必要な感じのSQLが本当に苦手です。
全然思いつかずに今日も半日を浪費してしまいました。
何かコツのようなものがあるのでしょうか。

お礼は明日の夜になってしまいますが何卒よろしくお願いします。

※連投すみません。削除も修正もできなかったので連投になってしまいました。
一番重要な説明をコピペミスしてしまいました。
明日になれば削除できるようなので古い方は明日削除致しますm(__)m

---ここから---
今日は9/24という想定で各部署の10営業日前の日付を取得したいのですが良い方法が思いつきません。
(ここ↓を参考にしたらできそうな気がしましたが私の頭では無理でした。。。)
http://oshiete.goo.ne.jp/qa/6677209.html

【休日テーブル】
部署コード, 休日
-----------------
busyo1,   9/13
b...続きを読む

Aベストアンサー

あまり深く考えていませんので、件数が多いと使いものにならないかもしれません。

with 休日テーブル as (
select 'busyo1' 部署コード, date'2014-09-13' 休日 from dual
union all select 'busyo1' 部署コード, date'2014-09-14' 休日 from dual
union all select 'busyo1' 部署コード, date'2014-09-20' 休日 from dual
union all select 'busyo1' 部署コード, date'2014-09-21' 休日 from dual
union all select 'busyo1' 部署コード, date'2014-09-23' 休日 from dual
union all select 'busyo2' 部署コード, date'2014-09-07' 休日 from dual
union all select 'busyo2' 部署コード, date'2014-09-14' 休日 from dual
union all select 'busyo2' 部署コード, date'2014-09-21' 休日 from dual
union all select 'busyo3' 部署コード, date'2014-09-20' 休日 from dual
)
, 日付 as (
select trunc(/* sysdate */ date'2014-09-24' - 1) - level 日付
from dual
--とりあえず過去30日分の日付
connect by level <= 30)
select 部署コード, 日付
from (
select 部署コード, 日付, count(*) over(partition by 部署コード order by 日付 desc) cnt
from (select distinct 部署コード from 休日テーブル) 部署マスタ
cross join 日付
where not exists (
select * from 休日テーブル where 部署マスタ.部署コード = 休日テーブル.部署コード and 日付.日付 = 休日テーブル.休日
)
)
where cnt = 10;

こまかい説明を書く時間がないので、そこはSQLから読みとってください。すみません・・・

あまり深く考えていませんので、件数が多いと使いものにならないかもしれません。

with 休日テーブル as (
select 'busyo1' 部署コード, date'2014-09-13' 休日 from dual
union all select 'busyo1' 部署コード, date'2014-09-14' 休日 from dual
union all select 'busyo1' 部署コード, date'2014-09-20' 休日 from dual
union all select 'busyo1' 部署コード, date'2014-09-21' 休日 from dual
union all select 'busyo1' 部署コード, date'2014-09-23' 休日 from dual
union all select 'busyo2' ...続きを読む


人気Q&Aランキング