University of Arizona, Department of Computer Science

CSc 120: Dates

Background

This problem involves managing a database of dates and events, e.g., for a calendar app or history website.

Problem Description

Suppose you wanted to offer a website or app to manage a database of dates and events. Such a database might be used to look up dates in the past ("on this date in history...", as in the sites mentioned above); or they might be used as a calendar service to provide reminders for future events. In either case, you need a program that can record and look up strings (i.e., events) associated with dates.

One catch here is reasoning about dates. People use many different formats to write dates, e.g., "December 25, 2016", "2016-12-25", and "12/25/2016", all of which represent the same date. The format that was used to insert an event into the database may or may not be the same as the format used to look up up that date. Your program therefore needs a way to reason about dates in different formats. This problem involves writing a class to maintain information about dates and events and reason about dates in different formats. The idea is to read a file containing a series of operations, where each operation refers to a database of dates and events, and process each operation in turn.

Input Formats

The input to the program is read from a file (see Expected Behavior below). Each line of the file is an operation, and is in one of the following two formats:
I   Date :   Event
R   Date

The fields in an operation are as follows:

Date
This specifies a date. It can be in any of the following three formats.

  • yyyy-mm-dd, where yyyy is a 4-digit sequence giving the year; mm is a 1- or 2-digit sequence giving the month; and dd is a 1- or 2-digit sequence giving the date.

    Example: 2017-02-31

  • mm/dd/yyyy, where yyyy is a 4-digit sequence giving the year; mm is a 1- or 2-digit sequence giving the month; and dd is a 1- or 2-digit sequence giving the date.

    Example: 02/31/2017.

  • MonthName   dd   yyyy, where MonthName is a three-letter sequence giving the name of a month (one of: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec); dd is a 1- or 2-digit sequence giving the date; and yyyy is a 4-digit sequence giving the year.

    Example: Feb 31 2017

NOTE: To simplify programming, we will assume that all months have 31 days.

Event
This is a string starting at the first non-whitespace character after the colon ":" following the date and going as far as the end of the line.

Examples of operations are:

I   2017-01-16 :  Martin Luther King Day
I   Mar 31 1997: Arizona Wildcats win National Basketball Title
R   03/31/1997

The first of these inserts the event "Martin Luther King Day" for the date Jan 16, 2017 into the calendar. The second adds the event "Arizona Wildcats win National Basketball Title" for the date March 31, 1997. The third item retrieves and prints out all events for the date March 31, 1997.

Expected Behavior

Write a Python program, in a file dates.py, that maintains a collection of Date objects, each of which has associated with a set of strings that refer to events for that date, processing these objects in accordance with operations read from an input file. Your program should behave as follows:

  1. Use input() (without any argument) to read the name of an input file.
  2. Read the file specified and process its contents as described below. Process the operation specified on each line as follows:

Dates are considered equal if their canonical representations (see below) are the same.

Some examples of input files and generated output are shown here.

Canonical Representation of Dates

A date with year yyyy, month mm, and day dd, where yyyy, mm, and dd are strings of digits, has a canonical (i.e., standard) representation given by
"{:d}-{:d}-{:d}".format( int(yyyy ), int(mm), int(dd))

The reason for converting yyyy, mm, and dd to numbers using int() and then back to strings is to remove any leading zeros.

Example:

Input formatCanonical representation
Mar 7 1997
Mar 07 1997
03/07/1997
3/7/1997
1997-3-07
1997-03-7
1997-3-7

Output Format

Print out the events for a given date one event per line using the statement
print("{}: {}".format(date_canonical, event))
where date_canonical is the canonical representation of the date, and event is an event for that date. The order in which events are printed out need not be the same as the order in which they were initially specified. If there are multiple events for a given date, they should be printed in alphabetical order.

Programming Requirements

Your program should implement the following classes:

class Date
An instance of this class describes a date.

Attributes: These should include:

  • the canonical representation of the date
  • the associated events (a collection of strings, e.g., a list or set).

Methods: These should include:
  • __init__(self, date, event), where date is the canonical representation of the date and event is a string for an event.
  • Getters for the attributes. (You don't really need setters for this class for this problem because once a Date object has been initialized it is not subsequently modified.)
  • __str__() and, optionally, a __repr()__ method.
  • A method to add an event (a string) to the collection of events for a Date object;
  • A method to convert a date string from the input format to the canonical representation. (see below)

class DateSet
An instance of this class describes a collection of dates.

Attributes: These should include:

  • a collection of Date objects. (A dictionary is a likely data structure for this. If you used this, what might you use as keys?).
Methods: These should include:

  • __init__();
  • A method to add a Date object to the collection of such objects.
  • optionally, __str__() and __repr()__ methods.

Additionally, you will need code for the following:

Your program should be appropriately modularized. In particular, other than the code mentioned above for processing input and converting dates to their canonical form, your code should be placed in methods in the appropriate class.

Errors

The following are errors.

  1. The input file cannot be read.

    Program response: Quit after printing the error message below. (Use a try-except construct for this.)

       “ERROR: Could not open file “ + filename 
    
  2. The operation is not I or R.

    Program response: Quit after printing the error message below.

       “ERROR: Illegal operation on line “ + input_line 
  3. A month is greater than 12 or a day of the month is greater than 31.

    Program response: Quit after printing the error message below.

       “ERROR: Illegal date on line “ + input_line
          

The tester will fully exercise all error cases that we expect you to handle. In other words, if you pass all error-producing tests, you can assume your error handling is fully correct and complete.

Examples

Some examples are shown here.