2017-04-01 67 views
0

我在我的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() 

回答

1

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查询。这应该使错误变得明显。

+0

感谢您的回复。我认为这绝对是一个格式错误,正如你注意的那样。我从最初的声明中删除了格式化字符串,然后我将elif search_date改为:'dt = datetime.datetime.strptime(search_date,fmt).date()' –

+0

因此这是一个问题 - - 这显然不会是一场比赛......但是当我打印出dt时,它显示出这样:2017-03-31这根本没有意义...... –

+0

以及我在另一个问题上发现了这个 - 所以它几乎可以解答我的问题:SQLite将日期存储为字符串。字符串按字节顺序排序。使用除%Y-%m-%d以外的格式将不会正确排序日期。 因此,对于SQLite,请始终将您的日期存储为%Y-%m-%d(无论如何这是peewee的默认值)。 –

相关问题