Next / Previous / Contents / Shipman's homepage

63. class DateField: Date field

This class represents a date as year, month and day. See the specification.

While scanning an encounter record, the year comes from the BaseEncounter object, while the month and day come from the record itself. Inside an actual DateField instance, the date is stored as an eight-character string of the form "YYYYMMDD".

baseclasses.py
# - - - - -   c l a s s   D a t e F i e l d   - - - - -

class DateField(FieldItem):
    '''Represents a date.

      Exports, beyond inherited items:
        DateField(encounter, yyyymmdd):
          [ yyyymmdd is a date as an eight-character string ->
              return a new DateField object representing that date ]
        .encounter:  [ as passed to constructor, read-only ]
        .yyyymmdd:   [ as passed to constructor, read-only ]
    '''

63.1. DateField.scanField()

This field scanner is a bit unusual, because it gets the year part of its input from the containing BaseCompiler object. All that we expect from the input is the numeric month and date as MMDD.

We're a bit permissive on what constitutes a valid date. We accept a date of "00" for situations where the month is known but the date is not. In any case, the MMDD_PAT class attribute is a compiled regular expression that matches a valid MMDD.

baseclasses.py
# - - -   D a t e F i e l d . s c a n F i e l d   - - -

    MMDD_PAT = re.compile (
        r'[01]'         # First digit of month
        r'[0-9]'        # Second digit of month
        r'[0-3]'        # First digit of day
        r'[0-9]')       # Second digit of day

    @staticmethod
    def scanField(encounter, scan, fieldName):
        '''Scan an MMDD-type date, adding the year from context.
        '''

        #-- 1 --
        # [ if the line in scan starts with a pattern that matches
        #   self.MMDD_PAT ->
        #     scan  :=  scan advanced past that pattern
        #     rawMMDD  :=  the matching pattern
        m = scan.tabReMatch(DateField.MMDD_PAT)
        if  m is None:
            scan.syntax("Expecting a date in MMDD format.")
        else:
            rawMMDD = m.group()

        #-- 2 --
        # [ if rawMMDD describes a valid month/day date ->
        #     I
        #   else ->
        #     Log()  +:=  error message
        #     raise SyntaxError ]
        mm = rawMMDD[:2]
        dd = rawMMDD[2:]
        if  not (1 <= int(mm) <= 12):
            scan.syntax("Month '%s' is invalid." % mm)
        if  not (0 <= int(dd) <= 31):
            scan.syntax("Date '%s' is invalid." % dd)

        #-- 3 --
        if  int(mm) >= 10:
            year = str(int(encounter.compiler.year) - 1)
        else:
            year = encounter.compiler.year

        #-- 4 --
        # [ encounter.(fieldName)  :=  encounter.compiler.year +
        #                              rawMMDD ]
        setattr(encounter, fieldName,
                DateField(encounter, year + rawMMDD))