混合datetime.strptime()参数 [英] Mixing datetime.strptime() arguments

查看:258
本文介绍了混合datetime.strptime()参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

混淆 datetime是一个很常见的错误.strptime() 使用以下格式格式化字符串和日期字符串参数:

It is quite a common mistake to mix up the datetime.strptime() format string and date string arguments using:

datetime.strptime("%B %d, %Y", "January 8, 2014")

其他方式:

datetime.strptime("January 8, 2014", "%B %d, %Y")

当然,它会在运行时失败:

Of course, it would fail during the runtime:

>>> datetime.strptime("%B %d, %Y", "January 8, 2014")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/_strptime.py", line 325, in _strptime
    (data_string, format))
ValueError: time data '%B %d, %Y' does not match format 'January 8, 2014'

但是,甚至在实际运行代码之前,是否有可能静态捕获此问题?是 pylint flake8 可以帮助的事吗?

But, is it possible to catch this problem statically even before actually running the code? Is it something pylint or flake8 can help with?

我已经尝试了PyCharm代码检查,但是两个代码段均未发出任何警告。可能是因为两个参数的类型相同-它们都是字符串,这使问题更加棘手。我们将必须实际分析字符串是否为日期时间格式的字符串。另外,语言注入 PyCharm / IDEA功能看起来很相关。

I've tried the PyCharm code inspection, but both snippets don't issue any warnings. Probably, because both arguments have the same type - they both are strings which makes the problem more difficult. We would have to actually analyze if a string is a datetime format string or not. Also, the Language Injections PyCharm/IDEA feature looks relevant.

推荐答案

我声称在一般情况下不能对其进行静态检查

请考虑以下代码段:

d = datetime.strptime(read_date_from_network(), read_format_from_file())

此代码可能是完全有效的,其中两个 read_date_from_network read_format_from_file 确实返回正确格式的字符串-否则它们可能是完全垃圾,都返回None或一些废话。无论如何,信息只能在运行时确定,因此,静态检查器将无能为力。

This code may be completely valid, where both read_date_from_network and read_format_from_file really do return strings of the proper format -- or they may be total garbage, both returning None or some crap. Regardless, that information can only be determined at runtime -- hence, a static checker is powerless.

此外,鉴于datetime.strptime的当前定义,即使我们正在使用静态类型的语言,我们也无法捕获此错误(在非常特殊的情况下除外)- -原因是此函数的签名从一开始就注定了我们

What's more, given the current definition of datetime.strptime, even if we were using a statically typed language, we wouldn't be able to catch this error (except in very specific cases) -- the reason being that the signature of this function doomed us from the start:

classmethod datetime.strptime(date_string, format)

在此定义中, date_string format 都是 strings ,尽管它们实际上有特殊含义。即使我们在静态类型语言中有类似的东西,例如:

in this definition, date_string and format are both strings, even though they actually have special meaning. Even if we had something analogous in a statically typed language like this:

public DateTime strpTime(String dateString, String format)

编译器(以及linter和其他所有人)仍然只能看到:

The compiler (and linter and everyone else) still only sees:

public DateTime strpTime(String, String)

这意味着以下任何一项都不可区分:

Which means that none of the following are distinguishable from each other:

strpTime("%B %d, %Y", "January 8, 2014") // strpTime(String, String) CHECK
strpTime("January 8, 2014", "%B %d, %Y") // strpTime(String, String) CHECK
strpTime("cat", "bat") // strpTime(String, String) CHECK






这并不是说它根本无法完成-确实存在一些针对静态类型语言(例如Java / C ++ / etc)的linter。当您将字符串文字传递给某些特定函数(例如printf等)时,该函数将检查字符串文字,但是只有当您直接使用文字格式字符串调用该函数时,才能执行此操作。在我介绍的第一种情况下,相同的短绒棉一样无助,因为尚不知道这些字符串的格式是否正确。


This isn't to say that it can't be done at all -- there do exist some linters for statically typed languages such as Java/C++/etc. that will inspect string literals when you pass them to some specific functions (like printf, etc.), but this can only be done when you're calling that function directly with a literal format string. The same linters become just as helpless in the first case that I presented, because it's simply not yet known if the strings will be the right format.

即短绒棉袜可能会对此发出警告:

i.e. A linter may be able to warn about this:

// Linter regex-es the first argument, sees %B et. al., warns you
strpTime("%B %d, %Y", "January 8, 2014")

,但无法对此发出警告:

but it would not be able to warn about this:

strpTime(scanner.readLine(), scanner.readLine())

现在,可以将同样的东西设计成python短绒毛绒,但我不知道我不相信它会非常有用,因为函数是一流的,因此我可以通过编写以下代码轻松击败(假设的python)lint:

Now, the same could be engineered into a python linter, but I don't believe that it would be very useful because functions are first-class, so I could easily defeat the (hypothetical python) linter by writing:

f = datetime.strptime
d = f("January 8, 2014", "%B %d, %Y")

然后我们几乎被抽空了。

And then we're pretty much hosed again.

奖金:错误的地方

这里的问题是 datetime.strptime 为每个字符串都隐含了含义,但是它不会将该信息显示给类型系统。可以做的是给两个字符串提供不同的类型-然后可以提高安全性,尽管会牺牲一些易用性。

The problem here is that the datetime.strptime gives implicit meaning to each of these strings, but it doesn't surface that information to the type system. What could have been done was to give the two strings differing types -- then there could have been more safety, albeit at the expense of some ease-of-use.

例如(使用PEP 484类型注释,是真实的东西!):

e.g (using PEP 484 type annotations, a real thing!):

class DateString(str):
  pass

class FormatString(str):
  pass

class datetime(date):
  ...
  def strptime(date_string: DateString, format: FormatString) -> datetime:
    # etc. etc.

然后,提供良好的在一般情况下不容易-尽管DateString和FormatString类需要注意验证其输入,因为同样,类型系统无法在该级别执行任何操作。

Then it would start to be feasible to provide good linting in the general case -- though the DateString and FormatString classes would need to take care of validating their input, because again, the type system can't do anything at that level.

后记:

我认为处理此问题的最佳方法是通过使用 strftime 方法,这是绑定到特定的datetime对象,并且仅接受格式字符串参数。通过给我们一个函数签名,当我们拥抱它时不会割伤我们,从而规避了整个问题。是的。

I think the best way to deal with this is to avoid the problem by using the strftime method, which is bound to a specific datetime object and takes just a format string argument. That circumvents the entire problem by giving us a function signature that doesn't cut us when we hug it. Yay.

这篇关于混合datetime.strptime()参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆