datetimeParseActions.py 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. # parseActions.py
  2. #
  3. # A sample program a parser to match a date string of the form "YYYY/MM/DD",
  4. # and return it as a datetime, or raise an exception if not a valid date.
  5. #
  6. # Copyright 2012, Paul T. McGuire
  7. #
  8. from datetime import datetime
  9. import pyparsing as pp
  10. from pyparsing import pyparsing_common as ppc
  11. # define an integer string, and a parse action to convert it
  12. # to an integer at parse time
  13. integer = pp.Word(pp.nums).setName("integer")
  14. def convertToInt(tokens):
  15. # no need to test for validity - we can't get here
  16. # unless tokens[0] contains all numeric digits
  17. return int(tokens[0])
  18. integer.setParseAction(convertToInt)
  19. # or can be written as one line as
  20. #integer = Word(nums).setParseAction(lambda t: int(t[0]))
  21. # define a pattern for a year/month/day date
  22. date_expr = integer('year') + '/' + integer('month') + '/' + integer('day')
  23. date_expr.ignore(pp.pythonStyleComment)
  24. def convertToDatetime(s,loc,tokens):
  25. try:
  26. # note that the year, month, and day fields were already
  27. # converted to ints from strings by the parse action defined
  28. # on the integer expression above
  29. return datetime(tokens.year, tokens.month, tokens.day).date()
  30. except Exception as ve:
  31. errmsg = "'%s/%s/%s' is not a valid date, %s" % \
  32. (tokens.year, tokens.month, tokens.day, ve)
  33. raise pp.ParseException(s, loc, errmsg)
  34. date_expr.setParseAction(convertToDatetime)
  35. date_expr.runTests("""\
  36. 2000/1/1
  37. # invalid month
  38. 2000/13/1
  39. # 1900 was not a leap year
  40. 1900/2/29
  41. # but 2000 was
  42. 2000/2/29
  43. """)
  44. # if dates conform to ISO8601, use definitions in pyparsing_common
  45. date_expr = ppc.iso8601_date.setParseAction(ppc.convertToDate())
  46. date_expr.ignore(pp.pythonStyleComment)
  47. date_expr.runTests("""\
  48. 2000-01-01
  49. # invalid month
  50. 2000-13-01
  51. # 1900 was not a leap year
  52. 1900-02-29
  53. # but 2000 was
  54. 2000-02-29
  55. """)