Ben Derey
Ben Derey

Reputation: 43

pyparsing - parsing dates


I am trying to parse dates from this format:
"11/2012-2014,2016,10/2012,11/2012-10/2014,2012-11/2012,".
the expected result is (((11, 2012), (2014)), (2016), (10, 2012), ...) Bad values:"11"
But something wrong.

month = Word(nums).setParseAction(self.validate_month)
year = Word(nums).setParseAction(self.validate_year)
date = Optional(month + Literal("/")) + year
date_range = Group(date + Optional(Literal("-") + date))
dates = date_range + ZeroOrMore(Literal(",") + date_range)    
command = StringStart() + dates + StringEnd()

Where am I wrong?
thanks

Upvotes: 4

Views: 1108

Answers (1)

PaulMcG
PaulMcG

Reputation: 63782

To get your desired output, you'll need to do a few things:

  • Add Group around your date expression

  • Suppress the punctuation from your output by using Suppress instead of Literal

See comments and sample output below:

# if there is a problem in your parse actions, you will need to post them
month = Word(nums)#.setParseAction(self.validate_month)
year = Word(nums)#.setParseAction(self.validate_year)

# wrap date in a Group
#date = Optional(month + Suppress("/")) + year
date = Group(Optional(month + Suppress("/")) + year)
date_range = Group(date + Optional(Suppress("-") + date))

dates = date_range + ZeroOrMore(Suppress(",") + date_range)
# your expression for dates can be replaced with this pyparsing helper
#   dates = delimitedList(date_range)

# The trailing ',' causes an exception because of your use of StringEnd()
command = StringStart() + dates + StringEnd()

test = "11/2012-2014,2016,10/2012,11/2012-10/2014,2012-11/2012"

# you can also use parseAll=True in place of tacking StringEnd 
# onto the end of your parser
command.parseString(test, parseAll=True).pprint()

Prints

[[['11', '2012'], ['2014']],
 [['2016']],
 [['10', '2012']],
 [['11', '2012'], ['10', '2014']],
 [['2012'], ['11', '2012']]]

Upvotes: 2

Related Questions