2

この問題を考慮してください:

生理の追加を開始する日付が過去にあります。これらの期間を追加すると、今日より後の日付になる場合は、停止して、最後の日付が何であるかを確認したいと思います。

これは、メンバーシップの引き落とし日を計算するための機能です。たとえば、メンバーが 2007-01-31 に参加します。彼は毎月引き落とされています。今日が 2013-03-29 だとしましょう (実際には atm です)。そのため、2007 年 1 月 31 日以降の月数のカウントを開始する必要があり、今日の日付を過ぎたら停止する必要があります。次の引き落とし日は 2013 年 3 月 31 日であることがわかります。

これを実装するために dateutil ライブラリを使用しています。現在の日付を超えるまで、relativedelta を while ループに追加します。(おそらく最善の方法ではないことはわかっていますが、私はまだ Python の初心者であり、これは概念実証です)。問題は、2007 年 1 月 31 日に 1 か月追加すると、次の日付が 2007 年 2 月 28 日になることです。これは正しいことです。しかし、次の反復では日付は 2007-03-28 になります。これは、dateutil が 28 日を月の最終日として認識せず、そのまま維持して 3 月の最終日まで反復するためです。もちろん、これは完全に有効な実装です。次に、dateutils rrule オブジェクトを試してみましたが、原則は同じです。日付のリストを出力しますが、日数が足りない月は単純にスキップします。

period = rrule(MONTHLY, interval=1, dtstart=datetime.date(2012, 5, 31), until=datetime.date(2013, 3, 29))
print(list(period))

それから私は別のアプローチを考えました:

2007 年 1 月 31 日から 2013 年 3 月 29 日までの期間の期間の数を数えることができれば、それらの期間の数を startdate に追加することができ、dateutil は正しい日付を返します。
問題は、期間が必ずしも 1 か月ではないことです。たとえば、4 週間、四半期、または 1 年の場合もあります。

私は、relativedelta を取得して、それを別の relativedelta で割って、後者が最初に入る回数を取得する方法を見つけることができませんでした。

誰かが私を正しい方向に向けることができれば、私はそれを感謝します. たとえば、これを実行できるライブラリはありますか (タイムスパンを互いに分割し、月や週などの特定のタイムブロックで結果を出力します)? おそらく、期間を入力として受け入れるdatediff関数がありますか(たとえば、vbscriptでは、週、月、日など、必要な期間の2つの日付の差を取得できます)。おそらくまったく異なる解決策はありますか?

完全を期すために、コードを含めますが、テキストですべてが説明されていると思います。

def calculate(self, testdate=datetime.date.today()):
    self._testdate = testdate


    while self.next < self._testdate:
        self.next += self._ddinterval
    self.previous = self.next - self._ddinterval
    return self.next

ありがとう、

エリック

編集:私は今、それが想定されていることを行うソリューションを持っていますが、Pythonic、エレガント、または高速ではありません。質問は同じままです。誰かがより良い解決策を思いつくことができれば、してください。これが私が思いついたものです:

def calculate(self, testdate=datetime.date.today()):
    self._testdate = testdate

    start = self.next
    count = 0
    while self.next < self._testdate:
        count += 1
        self.next = start + (count * self._ddinterval)
    self.previous = self.next - self._ddinterval
    return self.next
4

2 に答える 2

2

次のループの開始点として期間を追加した後に新しい値を使用する代わりに、代わりに増加し続けるデルタを作成します。

today = datetime.date.today()
start = datetime.date(2007, 1, 31)
period = relativedelta(months=1)

delta = period
while start + delta < today:
    delta += period

next = start + delta

これにより、次の結果が得られます。

>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> today = datetime.date.today()
>>> start = datetime.date(2007, 1, 31)
>>> period = relativedelta(months=1)
>>> delta = period
>>> while start + delta < today:
...     delta += period
... 
>>> delta
relativedelta(years=+6, months=+3)
>>> start + delta
datetime.date(2013, 4, 30)

これは、四半期や年を含む可変期間の長さで機能します。正確な週または日で測定された期間については、timedelta()オブジェクトも使用できますが、これは一般的な解決策です。

月や四半期などの可変幅の期間を使用する場合、期間を「分割」することはできません。丸一日で測定された期間の場合、単純に 2 つの日付の差を (timedelta から) 日に変換し、モジュラスを取得できます。

period = datetime.timedelta(days=28)  # 4 weeks
delta = today - start
remainder = delta.days % period.days
end = today + datetime.timedelta(days=remainder)

これは次を与えます:

>>> period = datetime.timedelta(days=28)  # 4 weeks
>>> delta = today - start
>>> remainder = delta.days % period.days
>>> today + datetime.timedelta(days=remainder)
datetime.date(2013, 4, 17)
于 2013-04-03T16:55:08.180 に答える