在Python中将字符串转换为日期时间
问题描述:
我在我的sqlite数据库中搜索日期时遇到了一些问题(使用peewee作为ORM)。如果用户以03/31/2017格式输入特定日期,即使这是我数据库中的有效日期,也不会发生任何事情。我很确定这是一些格式问题,但是我在搜索输入和数据库查询中使用了相同的格式 - 所以不确定会出现什么问题。在Python中将字符串转换为日期时间
from collections import OrderedDict
import datetime
import os
from peewee import *
db = SqliteDatabase('wlg.db')
fmt = '%m/%d/%Y'
class Entry(Model):
notes = TextField()
name = TextField()
task = TextField()
minutes = IntegerField()
date = DateField(formats=[fmt])
class Meta:
database = db
def initialize():
"""Create database and table if they don't exist"""
db.connect()
db.create_tables([Entry], safe=True)
def clear():
os.system('cls' if os.name == 'nt' else 'clear')
def menu_loop():
"""Show the menu"""
choice = None
while choice != 'q':
clear()
print("Enter 'q' to quit")
for key, value in menu.items():
print('{}) {}'.format(key, value.__doc__))
choice = input('Action: ').lower().strip()
if choice in menu:
clear()
menu[choice]()
def add_entry():
"""Add an entry"""
print("Enter your name or 'm' to return to main menu.")
while True:
name = input('> ')
if name.lower().strip() != 'm':
task = input("What task did you do? ")
minutes = input("How many minutes did it take? ")
notes = input("Please enter any notes about the task: ")
date = datetime.date.today().strftime(fmt)
Entry.create(name=name, task=task, minutes=minutes, notes=notes, date=date)
input("Hit Enter/Return to go back and add a task or view previous entries.")
break
else:
menu_loop()
def view_entries(search_employee=None, search_date=None, search_time=None, search_term=None):
"""View previous entries"""
entries = Entry.select().order_by(Entry.date.desc())
if search_employee:
entries = entries.where(Entry.name.contains(search_employee))
elif search_date:
dt = datetime.datetime.strptime(search_date, fmt)
entries = entries.where(Entry.date == dt)
elif search_time:
entries = entries.where(Entry.minutes == int(search_time))
elif search_term:
entries = entries.where((Entry.task.contains(search_term))|(Entry.notes.contains(search_term)))
for entry in entries:
date = entry.date.strftime(fmt)
print(date)
print('='*len(date))
print("Name: " + entry.name)
print("Task: " + entry.task)
print("Minutes Taken: " + str(entry.minutes))
print("Task Notes: " + entry.notes)
print("Date: " + date)
print('n) next entry')
print('q) return to main menu')
next_action = input('Action: [Nq] ').lower().strip()
if next_action == 'q':
break
def search_by_employee():
view_entries(search_employee=input('Search query: '))
def search_by_date():
view_entries(search_date=input('Enter Date in Format(mm/dd/yyyy)): '))
def search_by_time():
view_entries(search_time=input('Search query: '))
# while True:
# search_time = (input('Search query: '))
# try:
# search_time = int(search_time)
# view_entries(search_time)
# except ValueError:
# print("Not a valid entry. Please try again")
def search_by_term():
view_entries(search_term = input('Search query: '))
def search_entries():
"""Search previous entries"""
# view_entries(input('Search query: '))
while True:
lookup = input("Lookup by Employee(E), Date(D), Time(T) or Search Term(S): ")
lookup.lower()
if lookup == 'e':
search_by_employee()
break
elif lookup == 'd':
search_by_date()
break
elif lookup == 't':
search_by_time()
break
elif lookup == 's':
search_by_term()
break
else:
print("Sorry invalid option. Please try again")
def delete_entry(entry):
"""Delete an entry"""
pass
menu = OrderedDict([
('a', add_entry),
('v', view_entries),
('s', search_entries)
])
if __name__ == '__main__':
initialize()
menu_loop()
答
03/31/2017这里不是有效的日期(法国)。
如果你想特定于语言环境的日期处理,我相信python datetime支持它。
Locale date formatting in Python
但是,如果你的应用有国际用户,你应该非常,非常小心,因为2017年1月2日是依赖于全球用户来的部分2月1日或1月2日从。
我发现文本日期更好显示。例如,用法语说它是“1erFévrier”,但如果网站设置为英语,那么“2月1日”是非歧义的,绝对没问题。
但是,显示“02/01”正在寻求麻烦。
//结束咆哮。
假说可以解释您的问题:
使用datetime.datetime,但你的列是没有时间的日期。转换中可能出现问题。使用适当的类型总是一个好主意。
添加print()以确保您的日期正确转换为python日期对象。
您声明:
date = DateField(formats=[fmt])
既然有“FMT”规范这让我觉得,peewee执行某种(ISO YYYY-MM-DD)SQLite的内部日期格式之间的内部转换,并可能需要“mm/dd/yyyy”字符串而不是日期对象。你应该检查这个。
另外检查你的ORM peewee是否有方法显示它发出的SQL查询。这应该使错误变得明显。
感谢您的回复。我认为这绝对是一个格式错误,正如你注意的那样。我从最初的声明中删除了格式化字符串,然后我将elif search_date改为:'dt = datetime.datetime.strptime(search_date,fmt).date()' –
因此这是一个问题 - - 这显然不会是一场比赛......但是当我打印出dt时,它显示出这样:2017-03-31这根本没有意义...... –
以及我在另一个问题上发现了这个 - 所以它几乎可以解答我的问题:SQLite将日期存储为字符串。字符串按字节顺序排序。使用除%Y-%m-%d以外的格式将不会正确排序日期。 因此,对于SQLite,请始终将您的日期存储为%Y-%m-%d(无论如何这是peewee的默认值)。 –