datetime.strptime()参数顺序的问题

提出问题

经常会错写datetime.strptime(string, format),颠倒两个参数的顺序而写成datetime.strptime(format, string)re.find(pattern, string)相混淆.

分析问题

datetime.strptime()

1
2
3
4
5
6
strptime(string, format) method of builtins.type instance
string, format -> new datetime parsed from a string (like time.strptime()).

#Case
In [6]: datetime.strptime("8 May, 2019", "%d %B, %Y")
Out[6]: datetime.datetime(2019, 5, 8, 0, 0)

strptime的函数命名不太好, 词义模糊, 不如直接叫str2time. string是source, time是result.

本函数的工作是parse a string to produce a time object. strptime 的字面含义读起来却像是毫无意义的string to parse time或者是读成相反的含义parse time to produce a string.妥协的处理方法理解为”string parsed” to time.将strp当做一个组合名词strp2time

官方的strptime命名比较str2time的优点是存在动词parse,点出函数的内部逻辑需要做的核心工作是解析,将普通的字符串解析成为有实际价值和意义的时间对象.(更像是开发者提醒自己非写给API的用户)

1
2
3
datetime.strptime(string, format)
#扩展为
def strptime(src_string, parsed_format) -> "dst_time_object":

这样看来strptime还是符合 source to destination 的模式.

容易混淆string与format顺序的一个直接原因是存在re.match(pattern, str), 按照module re的这个思路, 要事第一,对strptime(string, format)的处理应该将format拿到前面.

对此的理解:

一, source to destination是惯例, strptime(string, format)没有打破惯例
二, regex突破了惯例, 可能因为consturct regex需要花费较多脑力,而其他如time-format并不需要.
(regex的所有的methods都是将构建regex-pattern作为第一个参数)

三, 处理strptime从字面含义去引导直觉. strptime(string, parsed-format) to a time-object

datetime.strftime()

容易混淆的另外一个原因是strptime的逆函数strftime

1
2
3
4
5
6
strftime(format)
format -> strftime() style string.
In [8]: dt
Out[8]: datetime.datetime(2019, 5, 8, 0, 0)
In [9]: dt.strftime("%d %B, %Y")
Out[9]: '08 May, 2019'

strftime是time2str

strftime (string format time)这个命名的影响, 很容易写作

1
datetime.strftime("%d %B, %Y", time_obj)

可能想一下会意识到没有充分利用time_obj已经是datetime object这个既成事实, 应该打开其内建的工具箱.
strftime 中的str是多余的, 既然是format, return的结果一定是string.去掉str只留下 ftime更为简洁.
strftime对比str2time的优点,也是有一个显性的动词format.
strptime(string,parsed_format)对应

1
2
#strftime可以写为
def strftime(self, format) -> string:

观察time_object.strftime(format) - > string 的结构,遵循 src to dst 的原则.作为src的time_object写在前面.输出的结果为string.

总结, 

strptime def strptime(src_string, parsed-format) ->dst_time 与`src_time_object.strftime(string_format)都遵循`src to dst 的原则,引起歧义的根源是两个函数的命名.
解决方案 strptime 直觉扩展为strp string parsed + to + timet
strftime,将多余的str去掉,ftime format time , str当做冗余的形容词修饰format. stringly format.
P.S. format time to string不是一个好的解决方案,因为颠倒了src和dst.
两个动词是核心,parse or format.如果是parse的工作,输出结果time_object.做format的工作,就return string.

应用时刻的思维链条:
parse -> parse src_string to dst_time -> string parsed to time-> datetime.strptime(src_string, format)

format -> format src_time to dst_string-> stringly format time to string ->time_object.strftime(format)

1)辨析parse or format 2)都遵循 src to dst 3) str[pf]time顺序不变.

除了re.search(pattern, src)之外,还有一个不守规矩的特例.

1
2
3
4
5
6
In [12]: "source to destination".split()                                                                                      
Out[12]: ['source', 'to', 'destination'] #遵循source to destination, convert src_str to dst_list
#逆操作却将要输出的结果放在了前面.
In [13]: " ".join(['source', 'to', 'destination'])
Out[13]: 'source to destination'
#显然['source', 'to', 'destination'].join(" ")更为合理 convert src_list to dst_string

可能的解释, Python将所有涉及string的操作集中在了一处.

1
2
3
4
In [16]: len([m for m in dir(str) if not m.startswith("__")])                                                                 
Out[16]: 45
In [17]: len([m for m in dir(list) if not m.startswith("__")])
Out[17]: 11

methods of string 是list的四倍.

辨析特例与常规.

regex和”,”.join是特例, strptime, strftime, str.split是常规.

date and clock

Maintain system time是操作系统提供的最基础的service API.

1
2
3
4
5
6
7
8
9
10
$ date -u
$ sudo hwclock -u
2019-05-08 20:19:14.764965+08:00
#str2time,
$ date -d "08 May 2019" +"%c"
Wed 08 May 2019 14:00:00 AM CST
#time2str, strftime
$ date +"%d %B, %Y"
08 May, 2019
#思路与strptime, strftime一致.

参考资料

strftime() and strptime() Behavior
Python strptime() - string to datetime object

datetime — Basic date and time types — Python 3.7.3 documentation

How To Format Date For Display or Use In a Shell Script - nixCraft

Convert string to date in bash - Stack Overflow

GNU Coreutils: Examples of date

date command in Linux with examples - GeeksforGeeks