16

次の形式で日付を示す文字列があります。

x minutes/hours/days/months/years ago

Pythonを使用してそれを日時に解析する必要があります。

dateutil ではできないようです。

それを行う方法はありますか?

4

9 に答える 9

13

確かにあなたはそれを行うことができます。あなただけが必要ですtimedelta

s = "3 days ago"
parsed_s = [s.split()[:2]]
time_dict = dict((fmt,float(amount)) for amount,fmt in parsed_s)
dt = datetime.timedelta(**time_dict)
past_time = datetime.datetime.now() - dt

余談ですが、timedelta のように機能する があるdateutilように見えますが、コンストラクターは引数にandも受け入れます (引数は整数である必要があるようです)。relativedeltamonthsyears

于 2012-09-24T13:38:35.200 に答える
8

これは s で簡単に行うことができますtimedelta:

import datetime

def string_to_delta(string_delta):
    value, unit, _ = string_delta.split()
    return datetime.timedelta(**{unit: float(value)})

生産:

>>> string_to_delta("20 hours ago")
datetime.timedelta(0, 72000)

これには、月/年を処理するための追加の作業が必要になりますが、月を日付に追加することはあいまいな操作ですが、意味がわかっている場合は簡単に追加できるはずです。

実際の時間を取得するには、単純に からデルタを取りdatetime.datetime.now()ます。

于 2012-09-24T13:39:17.607 に答える
1

完全に誇張されたソリューションですが、もっと柔軟なものが必要でした:

def string_to_delta(relative):
    #using simplistic year (no leap months are 30 days long.
    #WARNING: 12 months != 1 year
    unit_mapping = [('mic', 'microseconds', 1),
                    ('millis', 'microseconds', 1000),
                    ('sec', 'seconds', 1),
                    ('day', 'days', 1),
                    ('week', 'days', 7),
                    ('mon', 'days', 30),
                    ('year', 'days', 365)]
    try:
        tokens = relative.lower().split(' ')
        past = False
        if tokens[-1] == 'ago':
            past = True
            tokens =  tokens[:-1]
        elif tokens[0] == 'in':
            tokens = tokens[1:]


        units = dict(days = 0, seconds = 0, microseconds = 0)
        #we should always get pairs, if not we let this die and throw an exception
        while len(tokens) > 0:
            value = tokens.pop(0)
            if value == 'and':    #just skip this token
                continue
            else:
                value = float(value)

            unit = tokens.pop(0)
            for match, time_unit, time_constant in unit_mapping:
                if unit.startswith(match):
                    units[time_unit] += value * time_constant
        return datetime.timedelta(**units), past

    except Exception as e:
        raise ValueError("Don't know how to parse %s: %s" % (relative, e))

これは次のようなものを解析できます:

  • 2 days ago
  • in 60 seconds
  • 2 DAY and 4 Secs
  • in 1 year, 1 Month, 2 days and 4 MICRO
  • 2 Weeks 4 secs ago
  • 7 millis ago

巨大ですが:月と年をそれぞれ30日と365日に単純化します。場合によっては十分ですが、常にあなたが望むものではありません。

于 2013-11-07T11:45:08.157 に答える
0

pip3を使用して依存関係をインストールしてください

from datetime import date
from dateutil.relativedelta import relativedelta
import re

baseDate = date.today() #date(2020, 4, 29)

hoursPattern = re.compile(r'(\d\d?\d?) hours? ago')
daysPattern = re.compile(r'(\d\d?\d?) days? ago')
weeksPattern = re.compile(r'(\d\d?\d?) weeks? ago')
monthsPattern = re.compile(r'(\d\d?\d?) months? ago')
yearsPattern = re.compile(r'(\d\d?\d?) years? ago')


days = 0
daysMatch = daysPattern.search(ago)
if daysMatch:
    days += int(daysMatch.group(1))

hours = 0
hoursMatch = hoursPattern.search(ago)
if hoursMatch:
    hours += int(hoursMatch.group(1))

weeks = 0
weeksMatch = weeksPattern.search(ago)
if weeksMatch:
    weeks += int(weeksMatch.group(1))

months = 0
monthsMatch = monthsPattern.search(ago)
if monthsMatch:
    months += int(monthsMatch.group(1))

years = 0
yearsMatch = yearsPattern.search(ago)
if yearsMatch:
    years += int(yearsMatch.group(1))

yourDate = baseDate - relativedelta(hours=hours, days=days, weeks=weeks, months=months, years=years)
于 2020-04-30T20:11:44.300 に答える