2

私は現在、秒数を指定して時間を生成しています。これは私が非常に迅速に思いついたものです。うまく機能しますが、かなり醜いです。

これをよりエレガントにするためのトリックを(複雑にしたり、あれやこれに頼ったりせずに)考えることはできませんが、ここにいくつかのヒントがある人がいるかもしれません。

ありがとう!

def humanizeTime(seconds):
  if seconds < 60:
    return "%d seconds" % int(round(seconds))
  else:
    minutes = seconds / 60.0
    if minutes < 60:
      return "%d minutes %d seconds" % divmod(seconds, 60)
    else:
      hours = minutes / 60.0
      if hours < 24:
        return "%d hours %d minutes" % divmod(minutes, 60)
      else:
        days = hours / 24.0
        if days < 7:
          return "%d days" % int(round(days))
        else:
          weeks = days / 7.0
          if weeks < 4:
            return "%d weeks" % int(round(weeks))
          else:
            months = days / 30.0
            if months < 12:
              return "%d months" % int(round(months))
            else:
              return "%d years" % int(round(days / 365.0))

編集:

上記の内容 (これも 2 フィールドを超えることはありません) を適切な文法で計算できる優れたライブラリがあれば、間違いなく参加します。

これを計算できるライブラリでは、最大2つのフィールドのみを表示するために、このようなコード(または以下に示す回答の一部)を記述する必要があるため、これを行うものは見つかりません。

4

3 に答える 3

5

免責事項

この回答は、OP によって示されるコードを表現するよりPythonicな方法の例です。これは、高次関数を使用した単なる楽しいコーディング演習であり、実際の時間間隔を処理するための提案された、正気でさえないオプションではありません。

実際の時間とカレンダーの計算は簡単でも自明でもないことを忘れないでください。この問題については、十分にテストされ成熟したライブラリを使用することを常にお勧めします。


そうは言っても、これを行う方法は次のとおりです。明らかによりエレガントです。

# A function to generate the divisions list
def divisions(l, v):
    l.append(l[-1] * v)
    return l

# A function to reduce the divisions list
def reduction(l, v):
    q, r = divmod(l[-1], v)
    l[-1] = q
    l.append(r)
    return l

TIME_STEPS = (60, 60, 24, 7, 30, 12)
DIVISIONS = reduce(divisions, TIME_STEPS, [1])[1:]
DIVISIONS.reverse()

# The "seconds" variable holds the time interval in seconds
seconds = 6000
fragments = reduce(reduction, DIVISIONS, [seconds])

# Fragments is a list: [years, months, weeks, days, hours, minutes, seconds]
# In this example: [0, 0, 0, 0, 1, 40, 0]

# And here's the readability part
NAMES = ("years", "months", "weeks", "days", "hours", "minutes", "seconds")
readable = " ".join("%d %s" % (v, n) for v, n in zip(fragments, NAMES) if v > 0)

# Final result: readable = "1 hours 40 minutes"

ほとんどのリストが削減中に変更されていることに注意してください。これには少し疑問があります。かなり純粋な関数型プログラミング言語では、これを書くことで私は燃え尽きる可能性があります。しかし、Python は関数型プログラミング言語ではないため、それほど悪くはありません。

また、示されているコードの半分はDIVISIONSリストを計算するためのものであることに注意してください。これは常に同じであるため、手動で事前に計算できます。

于 2012-07-02T22:45:49.860 に答える
1

hh:mm:ssフォーマットがはるかに読みやすいので、これはうまくいくと思います。

>>> import datetime
>>> str(datetime.timedelta(seconds=1000))
'0:16:40'
于 2012-07-02T22:13:32.997 に答える
1

次のようなものはどうでしょうか。

> import datetime
> import re
>
> def get_duration(sec):
...    return re.sub(r'(\d+):(\d\d):(\d\d)', r'\1 hrs, \2 mins, \3 secs',
...                  str(datetime.timedelta(seconds=sec)))
...
> get_duration(0)
'0 hrs, 00 mins, 00 secs'
> get_duration(86401)
'1 day, 0 hrs, 00 mins, 01 secs'
> get_duration(691200)
' 8 days, 0 hrs, 00 mins, 00 secs'

月、週などは処理しません。繰り返しますが、過去数週間を正しく処理するのは大変な作業です。datetime.timedeltaこれにより、明示的な数学やその他の醜さをあまり必要とせずに、適切なソリューションへの道をかなり進むことができると思います。

そうは言っても、この回答で提案されているdateutilモジュールを見てください。私はさまざまな組み込みデバイスで多数のタイム ルーチンを作成してきましたが、極度の挑発なしにもう一度作成することを検討することさえありません。

于 2012-07-03T03:30:19.100 に答える