2011-12-06 13 views
19

こんにちは、なぜこれが起こっているのか理解するためには助けが必要です。ときESTIMATED_DURATION> self.get_program_duration()負の値を持つPython timedeltaの問題

def get_program_time_budget(self): 
    return self.estimated_duration-self.get_program_duration() 

すべての罰金をが、これは物事が面白い取得、他の道を行くとき: 私はイベントプログラムに「残り時間」を追跡する方法があります。

結果がユーザーに表示されます。結果-5分を取得する方法を

Estimated 11 hours Allocated  11 hours 5 minutes Remaining  -1 day 23 hours 55 minutes 

任意のアイデア:結果が負になるとき

Estimated 11 hours Allocated  10 hours 55 minutes  Remaining  5 minutes 

それは、このしていますか?

def format_duration(value): 
    try: 
    delim = ':' 
    toks = value.split(',') 
    hour = minute = '' 
    d_string = value.count('day') and toks[0] or '' 
    h, m, s = d_string and toks[-1].strip().split(delim) or value.split(delim) 
    try: 
     hour = int(h) 
    except: 
     pass 
    try: 
     minute = int(m) 
    except: 
     pass 
    h_string = "%s%s%s" % (hour and hour or '', (hour and ' hour' or ''),(hour and hour > 1 and 's' or '') ) 
    m_string = "%s%s%s" % (minute and minute or '', (minute and ' minute' or ''),(minute and minute > 1 and 's' or '')) 
    return "%s %s %s" % (d_string, h_string, m_string) 
    except Exception, e: 
    logging.error("Error in format_duration -> %s. Duration value=%s" % (e, value)) 
    return ''v 
+1

これは、負の値に対して「timedelta」が働く方法です。結果は常に正規化され、 'days'値だけが負の値になります。日の値が-5の場合、他のフィールドを無効にしますか? –

+3

私たちは2つのtimedeltasを引き算する方法を知っています。私たちが知らないのは、あなたが結果を表示するために使用したコードです。より良いアドバイスをお寄せください。 –

+1

負のtimedelta値で正常に動作させたい場合( "-1分"はちょうど "-1分"、**では "-1日+23時59分"ではない)、 'relativetimedelta'モジュールを使うことができます[dateutil](http://labix.org/python-dateutil)にあります。 – florisla

答えて

35

あなたは、Pythonを使用している場合: - :EDIT

ここ ははtimedeltaフォーマッタ(しかし、それははtimedeltaとして格納されているので、strとはtimedelta値を受け取り、これはDjangoのフィルタであることに注意してください)です2.7以上であればtimedelta.total_seconds()を使用して、秒を正または負の秒数で表すことができます。

>>> datetime.timedelta(-1, 86100).total_seconds() 
-300.0 

これを使用すると、分を簡単に計算できます。

あなたはドキュメントから、次の等価式を使用することができますPythonの2.7を使用していない場合:

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6)/10.0**6 

編集:あなたはおそらく、結果を表示するためにはtimedeltaのデフォルトの文字列表現を使用しているように見えますが私の元の答えはそれほど有用ではないかもしれません。 - 正はtimedeltaに「」

def get_program_time_budget(self): 
    td = self.estimated_duration-self.get_program_duration() 
    if td.days < 0: 
     return '-' + str(datetime.timedelta() - td) 
    return str(td) 

これは、今はtimedeltaの代わりに文字列を返すでしょう、そして負timedeltasのために、それは前に付加します:私は結果を表示するために、このような何かを示唆しています。

+0

ありがとうございます。素晴らしい答えですが、私はデフォルトのstr形式を使用しません。私は自分のフォーマッタを持っています(秒を削除するなど)ので、timedeltaが必要です。 docsから数式を試して、total_secondsを実行します。 –

+0

その場合は、フォーマッタを正のtimedeltaに変換し、正面の ' - 'に変換する必要があります。 –

+0

残念ながら、フォーマッタのコードはDjangoフィルタですので、timedelta .__ str__(または__unicode__)を値としてとります - コードの質問を参照してください。 –

11

なぜですか?

//%の意図しない副作用として定義されている可能性があります。

datetimeクラスの実装が容易になる可能性があるためです。エポックの5分前は23時55分、0時-5分ではありません。

本当に問題ではありません。 daysseconds、およびmicrosecondsが正規化されていることがわかります。そして、それは簡単に回避することができます。

def format_timedelta(td): 
    if td < timedelta(0): 
     return '-' + format_timedelta(-td) 
    else: 
     # Change this to format positive timedeltas the way you want 
     return str(td) 

>>> format_timedelta(timedelta(minutes=-5)) 
'-0:05:00' 
+2

これはとても単純で天才です。ありがとうございました! –