python'x days ago'到datetime

时间:2012-09-24 13:33:48

标签: python datetime

我有以下列格式显示日期的字符串:

x minutes/hours/days/months/years ago

我需要使用python将其解析为日期时间。

似乎dateutil无法做到。

有办法吗?

9 个答案:

答案 0 :(得分:8)

当然可以做到。您只需要一个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

顺便说一下,看起来dateutil有一个relativedelta就像一个timedelta,但构造函数也接受monthsyears的参数(显然参数必须是整数)。

答案 1 :(得分:6)

这可以通过timedelta s轻松完成:

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()开始。

答案 2 :(得分:3)

因为您的论点类似于2天前,3个月前,2年前。下面的函数可能有助于获取参数的确切日期。首先需要导入以下日期工具

import datetime
from dateutil.relativedelta import relativedelta

然后实现下面的功能

def get_past_date(str_days_ago):
    TODAY = datetime.date.today()
    splitted = str_days_ago.split()
    if len(splitted) == 1 and splitted[0].lower() == 'today':
        return str(TODAY.isoformat())
    elif len(splitted) == 1 and splitted[0].lower() == 'yesterday':
        date = TODAY - relativedelta(days=1)
        return str(date.isoformat())
    elif splitted[1].lower() in ['hour', 'hours', 'hr', 'hrs', 'h']:
        date = datetime.datetime.now() - relativedelta(hours=int(splitted[0]))
        return str(date.date().isoformat())
    elif splitted[1].lower() in ['day', 'days', 'd']:
        date = TODAY - relativedelta(days=int(splitted[0]))
        return str(date.isoformat())
    elif splitted[1].lower() in ['wk', 'wks', 'week', 'weeks', 'w']:
        date = TODAY - relativedelta(weeks=int(splitted[0]))
        return str(date.isoformat())
    elif splitted[1].lower() in ['mon', 'mons', 'month', 'months', 'm']:
        date = TODAY - relativedelta(months=int(splitted[0]))
        return str(date.isoformat())
    elif splitted[1].lower() in ['yrs', 'yr', 'years', 'year', 'y']:
        date = TODAY - relativedelta(years=int(splitted[0]))
        return str(date.isoformat())
    else:
        return "Wrong Argument format"

然后您可以像这样调用函数:

print get_past_date('5 hours ago')
print get_past_date('yesterday')
print get_past_date('3 days ago')
print get_past_date('4 months ago')
print get_past_date('2 years ago')
print get_past_date('today')

答案 3 :(得分:2)

@mgilson 的回答在 dateutil.relativedelta 完成工作的地方对我不起作用:

根据@mosc9575 建议进行编辑

import datetime
from dateutil.relativedelta import relativedelta

time_ago = "1 month ago"
val, unit = time_ago.split()[:2]
past_time = datetime.datetime.now() - relativedelta(**{unit:int(val)})

答案 4 :(得分:0)

完全夸张的解决方案,但我需要更灵活的东西:

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天。并不总是你想要的,虽然这对某些情况来说已经足够了。

答案 5 :(得分:0)

在Python中将x hours ago转换为datetimex hour, y mins ago转换为datetime等的自定义函数。

函数采用使用RegExp解析的字符串类型的单个参数。可以自定义RegExp以匹配功能输入。

有关用法,请参见下面的示例。

import re
from datetime import datetime, timedelta


def convert_datetime(datetime_ago):
    matches = re.search(r"(\d+ weeks?,? )?(\d+ days?,? )?(\d+ hours?,? )?(\d+ mins?,? )?(\d+ secs? )?ago", datetime_ago)

    if not matches:
        return None

    date_pieces = {'week': 0, 'day': 0, 'hour': 0, 'min': 0, 'sec': 0}

    for i in range(1, len(date_pieces) + 1):
        if matches.group(i):
            value_unit = matches.group(i).rstrip(', ')
            if len(value_unit.split()) == 2:
                value, unit = value_unit.split()
                date_pieces[unit.rstrip('s')] = int(value)

    d = datetime.today() - timedelta(
        weeks=date_pieces['week'],
        days=date_pieces['day'],
        hours=date_pieces['hour'],
        minutes=date_pieces['min'],
        seconds=date_pieces['sec']
    )

    return d

用法示例:

dates = [
    '1 week, 6 days, 11 hours, 20 mins, 13 secs ago',
    '1 week, 10 hours ago',
    '1 week, 1 day ago',
    '6 days, 11 hours, 20 mins ago',
    '1 hour ago',
    '11 hours, 20 mins ago',
    '20 mins 10 secs ago',
    '10 secs ago',
    '1 sec ago',
]    

for date in dates:
    print(convert_datetime(date))

输出:

2019-05-10 06:26:40.937027
2019-05-16 07:46:53.937027
2019-05-15 17:46:53.937027
2019-05-17 06:26:53.937027
2019-05-23 16:46:53.937027
2019-05-23 06:26:53.937027
2019-05-23 17:26:43.937027
2019-05-23 17:46:43.937027
2019-05-23 17:46:52.937027

答案 6 :(得分: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)

答案 7 :(得分:0)

最简单的方法是使用dateparser:

import dateparser
date_ago="4 months ago" 
date=dateparser.parse(date).strftime("%Y-%m-%d")
date

输出:

'2020-01-08'

答案 8 :(得分:0)

datetime 是否有机会使用其他语言(意大利语)“x 天前至今”?

import locale\
locale.setlocale(locale.LC_ALL,'it_IT.UTF-8') 

没有任何区别。