2

余分なテキストとあいまいさを削除するために更新されました。

規則:
従業員は、各四半期の翌日に 8 時間の有給休暇を取得します。四半期、具体的には次のとおりです。

  • 1月1日~3月31日
  • 4月1日~6月30日
  • 7月1日~9月30日
  • 10 月 1 日~12 月 31 日

問題
Python を使用して、次の関数の内容を定義する必要があります。

def acrued_hours_between(start_date, end_date): 
    # stuff
    return integer

私は現在Pythonを使用していますが、このようなものへの正しいアプローチはどうなるのだろうと思っています.

ここでは、DateTime オブジェクトと、おそらく dateutil モジュールを使用すると役立つと思いますが、何らかの理由でこの問題を回避できません。

更新
問題は次のとおりであるため、計算はやや単純であると思います。

「start_date から end_date までの有給休暇は何時間ありますか?」上記の「ルール」が与えられます。
4

5 に答える 5

5

OPの編集では、実際の根本的な問題は次のとおりです。

「X 日付から Y 日付までに発生する有給休暇は何時間ですか?」

同意します。最も直接的で簡単な方法で計算します。たとえば、次のようになります。

import datetime
import itertools

accrual_months_days = (1,1), (4,1), (7,1), (10,1)

def accruals(begin_date, end_date, hours_per=8):
  """Vacation accrued between begin_date and end_date included."""
  cur_year = begin_date.year - 1
  result = 0
  for m, d in itertools.cycle(accrual_months_days):
    if m == 1: cur_year += 1
    d = datetime.date(cur_year, m, d)
    if d < begin_date: continue
    if d > end_date: return result
    result += hours_per

if __name__ == '__main__':  # examples
  print accruals(datetime.date(2010, 1, 12), datetime.date(2010, 9, 20))
  print accruals(datetime.date(2010, 4, 20), datetime.date(2012, 12, 21))
  print accruals(datetime.date(2010, 12, 21), datetime.date(2012, 4, 20))

もちろん、直接式の方が高速ですが、バグなしで実行するのは難しい場合があります。この「検査による修正」の例は、大規模なサンプルで一致することを確認することにより、より高速な式を自動的に調整するのに役立ちます。日付のペア (もちろん、四半期の最初と最後の日など、すべてのコーナー ケースを後者に含めるようにしてください)。

于 2010-06-15T00:34:33.693 に答える
1

特定の従業員のすべてのイベントを時間順に並べ替え、その順序でイベントをシミュレートし、利用可能な有給休暇日数がゼロを下回らないことを確認します。有給休暇申請は、値が -(時間数) のイベントです。1 月 1 日には +8 時間の値を持つイベントがあります。

データに変更が加えられるたびに、最初からシミュレーションを再実行します。

この方法の利点は、新しいイベントがその時点で有効であるが、以前は有効だった後のイベントが無効になるなど、空き日数が減少する状況を検出できることです。

これは中間結果をキャッシュに保存することで最適化できますが、従業員ごとに数百のイベントしかない可能性が高いため、この最適化はおそらく必要ありません。

于 2010-06-14T21:48:49.013 に答える
1

これは、昔ながらの整数演算で行うことができます。

from datetime import date

def hours_accrued(start, end):
    '''hours_accrued(date, date) -> int

    Answers the question "How many hours of Paid Time Off
      are accrued from X-date to Y-date?"

    >>> hours_accrued(date(2010, 4, 20), date(2012, 12, 21))
    80
    >>> hours_accrued(date(2010, 12, 21), date(2012, 4, 20))
    48
    '''
    return ( 4*(end.year - start.year)
        + ((end.month-1)/3 - (start.month-1)/3) ) * 8
于 2010-06-14T23:13:43.760 に答える
0

各日付範囲のタプルを設定します (四半期と呼びます)。タプルには、四半期 (カーディナル インデックスまたは開始日として)、四半期の最大経過時間、および四半期の使用時間数が格納されます。これが機能するようにソートされた一連のタプルが必要になるため、単純なリストはおそらく最良の選択肢ではありません。辞書はこれにアプローチするためのより良い方法かもしれません。四半期をキーとして、タプルで返される最大/使用済みエントリを使用して、「ソート」できるためです。

(注:元の説明を見て、答えを書き直しました)

四半期の日付でソートされた、特定の従業員のすべての四半期のセットのコピーを取得します。要求日が属する四半期に到達するまで、四半期ごとに割り当てられた休暇時間の最大値とその四半期に「費やされた」時間との差を合計して、四半期ごとに繰り返します。これにより累積時間が得られます。

要求された四半期に割り当てられた時間を累積時間に加えた時間が、要求された時間に満たない場合は、すぐに失敗し、要求を拒否します。それ以外の場合は、クエストの 4 分の 1 まで繰り返します。

累積時間が十分にある場合は、最初の計算からの残りの時間から始めて、四半期ごとに新しい利用可能な時間を計算しながら、コピーされたセットを繰り返し処理します。

いずれかの四半期の計算時間がゼロを下回った場合は、すぐに失敗し、要求を拒否します。それ以外の場合は、四半期がなくなるまで続行します。

すべての四半期が計算されたら、元のデータ セットをコピーで更新し、要求を許可します。

于 2010-06-14T22:04:55.340 に答える
0

問題の日付までのすべての空き日数を数えてから、それまでの使用日数を引いて、最大許容日数の値を求めます。

于 2010-06-14T21:50:13.173 に答える