有没有办法在dateutil中解析日期后获取"格式".例如:

>>> x = parse("2014-01-01 00:12:12")
datetime.datetime(2014, 1, 1, 0, 12, 12)

x.get_original_string_format()
YYYY-MM-DD HH:MM:SS # %Y-%m-%d %H:%M:%S

# Or, passing the date-string directly
get_original_string_format("2014-01-01 00:12:12")
YYYY-MM-DD HH:MM:SS # %Y-%m-%d %H:%M:%S

Update:我想给这个问题增加一个悬赏,看看是否有人可以添加一个答案,这个答案在传递一个普通日期字符串的字符串格式时起到同等作用.如果你想的话,它可以使用dateutil,但不一定非得如此.希望我们能在这里找到一些创造性的解决方案.

推荐答案

我的 idea 是:

  1. 创建一个对象,该对象包含一个你认为在日期模式中有might个候选说明符的列表(你添加的越多,你从另一端得到的可能性就越大)
  2. 解析日期字符串
  3. 根据您提供的日期和候选列表,为字符串中的每个元素创建一个可能的说明符列表.
  4. 重新组合它们,生成"可能"列表.

如果你只有一个候选人,你可以很确定这是正确的格式.但你通常会得到很多可能性(尤其是日期、月份、分钟和小时都在0-10范围内).

示例类:

import re
from itertools import product
from dateutil.parser import parse
from collections import defaultdict, Counter

COMMON_SPECIFIERS = [
    '%a', '%A', '%d', '%b', '%B', '%m',
    '%Y', '%H', '%p', '%M', '%S', '%Z',
]


class FormatFinder:
    def __init__(self,
                 valid_specifiers=COMMON_SPECIFIERS,
                 date_element=r'([\w]+)',
                 delimiter_element=r'([\W]+)',
                 ignore_case=False):
        self.specifiers = valid_specifiers
        joined = (r'' + date_element + r"|" + delimiter_element)
        self.pattern = re.compile(joined)
        self.ignore_case = ignore_case

    def find_candidate_patterns(self, date_string):
        date = parse(date_string)
        tokens = self.pattern.findall(date_string)

        candidate_specifiers = defaultdict(list)

        for specifier in self.specifiers:
            token = date.strftime(specifier)
            candidate_specifiers[token].append(specifier)
            if self.ignore_case:
                candidate_specifiers[token.
                                     upper()] = candidate_specifiers[token]
                candidate_specifiers[token.
                                     lower()] = candidate_specifiers[token]

        options_for_each_element = []
        for (token, delimiter) in tokens:
            if token:
                if token not in candidate_specifiers:
                    options_for_each_element.append(
                        [token])  # just use this verbatim?
                else:
                    options_for_each_element.append(
                        candidate_specifiers[token])
            else:
                options_for_each_element.append([delimiter])

        for parts in product(*options_for_each_element):
            counts = Counter(parts)
            max_count = max(counts[specifier] for specifier in self.specifiers)
            if max_count > 1:
                # this is a candidate with the same item used more than once
                continue
            yield "".join(parts)

还有一些样本测试:

def test_it_returns_value_from_question_1():
    s = "2014-01-01 00:12:12"
    candidates = FormatFinder().find_candidate_patterns(s)
    sut = FormatFinder()
    candidates = sut.find_candidate_patterns(s)
    assert "%Y-%m-%d %H:%M:%S" in candidates


def test_it_returns_value_from_question_2():
    s = 'Jan. 04, 2017'
    sut = FormatFinder()
    candidates = sut.find_candidate_patterns(s)
    candidates = list(candidates)
    assert "%b. %d, %Y" in candidates
    assert len(candidates) == 1


def test_it_can_ignore_case():
    # NB: apparently the 'AM/PM' is meant to be capitalised in my locale! 
    # News to me!
    s = "JANUARY 12, 2018 02:12 am"
    sut = FormatFinder(ignore_case=True)
    candidates = sut.find_candidate_patterns(s)
    assert "%B %d, %Y %H:%M %p" in candidates


def test_it_returns_parts_that_have_no_date_component_verbatim():
    # In this string, the 'at' is considered as a 'date' element, 
    # but there is no specifier that produces a candidate for it
    s = "January 12, 2018 at 02:12 AM"
    sut = FormatFinder()
    candidates = sut.find_candidate_patterns(s)
    assert "%B %d, %Y at %H:%M %p" in candidates

为了更清楚一点,下面是在iPython shell中使用此代码的一些示例:

In [2]: ff = FormatFinder()

In [3]: list(ff.find_candidate_patterns("2014-01-01 00:12:12"))
Out[3]:
['%Y-%d-%m %H:%M:%S',
 '%Y-%d-%m %H:%S:%M',
 '%Y-%m-%d %H:%M:%S',
 '%Y-%m-%d %H:%S:%M']

In [4]: list(ff.find_candidate_patterns("Jan. 04, 2017"))
Out[4]: ['%b. %d, %Y']

In [5]: list(ff.find_candidate_patterns("January 12, 2018 at 02:12 AM"))
Out[5]: ['%B %d, %Y at %H:%M %p', '%B %M, %Y at %H:%d %p']

In [6]: ff_without_case = FormatFinder(ignore_case=True)

In [7]: list(ff_without_case.find_candidate_patterns("JANUARY 12, 2018 02:12 am"))
Out[7]: ['%B %d, %Y %H:%M %p', '%B %M, %Y %H:%d %p']

Python-3.x相关问答推荐

Gekko优化超出了方程式的界限(由于某种原因,会产生变量)

Pandas :从元组字典创建数据帧

Django将任何查询显示为html表格

为什么我的Selenium脚本在密码元素上失败?

我不能使用拆分来分隔数据

使用Python按照其组/ID的紧密值的递增顺序映射数据框的两列

在 python 中使用正则表达式在行尾查找特定元素

如何在 histplot 中标记核密度估计

在不改变 python 中原始数组顺序的情况下,对多维字符串数组进行降序排序?

在判断列表变量时如何判断特定列的值并分配加权整数值

总结基于条件的值,如果不匹配则保留当前值

Dask worker post-processing

在气流中运行 DAG 时出现处理信号:ttou消息

如何在 Spyder 控制台中使用变量执行 Python 3.3 脚本?

使用逗号时,除了处理程序中的语法无效

导入 python 模块而不实际执行它

PIL 在图像上绘制半透明方形覆盖

如何使用 python 库连接到 poloniex.com websocket api

为什么排序列表比未排序列表大

在 macbook pro M1 上安装 Tensorflow 时出现zsh:非法硬件指令 python