<?PHP

#
#   Axis--Date.php
#   A Date Manipulation Object
#
#   Copyright 1999-2004 Axis Data
#   This code is free software that can be used or redistributed under the
#   terms of Version 2 of the GNU General Public License, as published by the
#   Free Software Foundation (http://www.fsf.org).
#
#   Author:  Edward Almasy (almasy@axisdata.com)
#
#   Part of the AxisPHP library v1.2.5
#   For more information see http://www.axisdata.com/AxisPHP/
#

class Date {

    # ---- PUBLIC INTERFACE --------------------------------------------------

    # object constructor
    function Date($BeginDate, $EndDate = NULL, $Precision = NULL, $DebugLevel = 0)
    {
        # set debug state
        $this->DebugLevel = $DebugLevel;

        if ($this->DebugLevel) {  print("Date:  Date(BeginDate=\"".$BeginDate."\" EndDate=\"".$EndDate."\" Precision=".$this->FormattedPrecision($Precision).")<br>\n");  }

        $MonthNames = array(
            "january"   => 1,
            "february"  => 2,
            "march"     => 3,
            "april"     => 4,
            "may"       => 5,
            "june"      => 6,
            "july"      => 7,
            "august"    => 8,
            "september" => 9,
            "october"   => 10,
            "november"  => 11,
            "december"  => 12,
            "jan" => 1,
            "feb" => 2,
            "mar" => 3,
            "apr" => 4,
            "may" => 5,
            "jun" => 6,
            "jul" => 7,
            "aug" => 8,
            "sep" => 9,
            "oct" => 10,
            "nov" => 11,
            "dec" => 12
            );

        # Formats we need to parse:
        #   1999-9-19
        #   1999-9
        #   9-19-1999
        #   19-9-1999
        #   Sep-1999
        #   Sep 1999
        #   Sep 9 1999
        #   September 9th, 1999
        #   1996,1999
        #   c1999
        #   1996-1999
        #   9/19/01
        #   9-19-01
        #   199909
        #   19990909
        #   09-Sep-1999
        #   09 Sep 1999

        # append end date to begin date if available
        $Date = $BeginDate;
        if ($EndDate!==NULL)
        {
            $Date .= " - ".$EndDate;
        }

        # strip off any leading or trailing whitespace
        $Date = trim($Date);

        # bail out if we don't have anything to parse
        if (strlen($Date) < 1) {  return;  }

        # check for and strip out inferred indicators ("[" and "]")
        $Prec = 0;
        if (preg_match("/\\[/", $Date))
        {
            $Prec |= DATEPRE_INFERRED;
            $Date = preg_replace("/[\\[\\]]/", "", $Date);
        }

        # check for and strip off copyright indicator (leading "c")
        if (preg_match("/^c/", $Date))
        {
            $Prec |= DATEPRE_COPYRIGHT;
            $Date = preg_replace("/^c/", "", $Date);
        }

        # check for and strip off continuous indicator (trailing "-")
        if (preg_match("/\\-$/", $Date))
        {
            $Prec |= DATEPRE_CONTINUOUS;
            $Date = preg_replace("/\\-$/", "", $Date);
        }

        # strip out any times
        $Date = preg_replace("/[0-9]{1,2}:[0-9]{2,2}[:]?[0-9]{0,2}/", "", $Date);
        $Date = trim($Date);
        
        $Date = strtolower($Date);
        
        # A regex to match short and long month names:
        $MonthRegex = "(?:jan(?:uary)?|feb(?:ruary)?|mar(?:ch)?|apr(?:il)?|may".
            "|jun(?:e)?|jul(?:y)?|aug(?:ust)?|sep(?:tember)?|oct(?:ober)?".
            "|nov(?:ember)?|dec(?:ember)?)";

        # Here we'll construct a template regex for dates
        # We want a single regex that covers all the different formats
        # of date we understand, with the various components of the
        # date pulled out using named subexpressions (eg: (?P<name>)).
        # Annoyingly, we can't re-use the same name for subexpressions
        # that will never both be matched at once.
        # So, we have to number them (year1, year2, etc) and figure
        # out which one did match.
        # Use XX_ThingNumber in the parameterized subexpressions
        # (eg XX_year1).
        # We'll use string substitutions later to convert the XX_ to
        # begin_ and end_

        $DateRegex = "(".
            # Matched formats are separated by |, as this isn't used in any of the formats
            # First alternative will match the following formats:
            # 1999-09-19 | 19990909 | 1999-09 | 199909 | 1999
            "(?:(?P<XX_year1>\d{4})(?:-?(?P<XX_month1>\d{1,2})(?:-?(?P<XX_day1>\d{1,2}))?)?)".
            # Second alternative will match the following formats:
            # 09-19-1999 | 19-09-1999 | 09/19/01 | 09-19-01
            "|(?:(?P<XX_month2>\d{1,2})[\/-](?P<XX_day2>\d{1,2})[\/-](?P<XX_year2>(?:\d{2,4})))".
            # Third alternative will match the following formats:
            # 09-Sep-1999 | 09 Sep 1999 | Sep-1999 | Sep 1999
            "|(?:(?:(?P<XX_day3>\d+)[ -])?(?P<XX_month3>".$MonthRegex.")[ -](?P<XX_year3>\d{4}))".            
            # Fourth alternative will match the following formats:
            # Sep 9 1999 | September 9th, 1999
            "|(?:(?P<XX_month4>".$MonthRegex.") (?P<XX_day4>\d{1,2})(?:(?:st|nd|rd|th),)? (?P<XX_year4>\d{4}))".
            ")";
        
        # If more formats are added, bump this.
        $NumberOfDateRegexes = 4;

        # Construct the begin and end regexes for the date range
        $BeginRegex = str_replace('XX','Begin', $DateRegex );
        $EndRegex   = str_replace('XX','End',   $DateRegex );
        
        # Glue them together, making the second one optional,
        # and do the matching.
        if ( preg_match("/".$BeginRegex.
                        "(?:(?:(?: - )|,)".$EndRegex.")?/",
                        $Date, $Matches ) )
        {
            # Pull out the Begin and End data from the matches array:
            foreach( array("Begin","End") as $Time )
            {
                eval(
                    # Extract the matching elements from the regex parse
                    '$'.$Time.'Day   = $this->ExtractMatchData($Matches,"'.
                    $Time.'_day",  $NumberOfDateRegexes );'   .
                    '$'.$Time.'Month = $this->ExtractMatchData($Matches,"'.
                    $Time.'_month",$NumberOfDateRegexes );'   .
                    '$'.$Time.'Year  = $this->ExtractMatchData($Matches,"'.
                    $Time.'_year", $NumberOfDateRegexes );'   .
                    # Convert named months to month numbers:
                    'if ( isset($'.$Time.'Month) && '                     .
                    '     !is_numeric($'.$Time.'Month))'                  .
                    '{'                                                   .
                    '  $'.$Time.'Month=$MonthNames[$'.$Time.'Month];'     .
                    '}'                                                   .
                    # Handle 2-digit years
                    'if ( isset($'.$Time.'Year) && '                      .
                    '     strlen($'.$Time.'Year)==2)'                     .
                    '{'                                                   .
                    '  $'.$Time.'Year += ($'.$Time.'Year>50)?1900:2000;'  .
                    '}'                                                   .
                    # Deal with D-M-Y format, where we can
                    'if ( isset($'.$Time.'Month) && $'.$Time.'Month>12)'  .
                    '{'                                                   .
                    '  $Tmp = $'.$Time.'Month;'                           .
                    '  $'.$Time.'Month = $'.$Time.'Day;'                  .
                    '  $'.$Time.'Day = $Tmp;'                             .
                    '}'
                    );
            }
        }
        
        # use current month if begin day but no begin month specified
        if (isset($BeginDay) && !isset($BeginMonth))
        {
            $BeginMonth = date("m");
        }

        # use current year if begin month but no begin year specified
        if (isset($BeginMonth) && !isset($BeginYear))
        {
            $BeginYear = date("Y");
        }

        # use begin year if end month but no end year specified
        if (isset($EndMonth) && !isset($EndYear))
        {
            $EndYear = $BeginYear;
        }
        
        # After we've shuffled around the numbers, check the result to see if
        # it looks valid, dropping that which doesn't.
        foreach( array("Begin","End") as $Time)
        {
            eval(
                # Discard invalid looking dates
                'if ( isset($'.$Time.'Year) && !($'.$Time.'Year >=1)) ' .
                '  { unset($'.$Time.'Year); } '                         .
                'if ( isset($'.$Time.'Month) && '                       .
                '     !( $'.$Time.'Month>=1 && $'.$Time.'Month<=12)) '  .
                '  { unset($'.$Time.'Month); } '                        .
                'if ( isset($'.$Time.'Day) && '                         .
                '     !( $'.$Time.'Day  >=1 && $'.$Time.'Day  <=31)) '  .
                '  { unset($'.$Time.'Day); } '
                );
        }
        
        # if no begin date found and begin date value is not illegal
        if (!isset($BeginYear)
                && ($BeginDate != "0000-00-00")
                && ($BeginDate != "0000-00-00 00:00:00"))
        {
            # try system call to parse incoming date
            $UDateStamp = strtotime($BeginDate);
            if ($this->DebugLevel > 1) {  print("Date:  calling strtotime to parse BeginDate \"".$BeginDate."\" -- strtotime returned \"".$UDateStamp."\"<br>\n");  }

            # if system call was able to parse date
            if (($UDateStamp != -1) && ($UDateStamp !== FALSE))
            {
                # set begin date to value returned by system call
                $BeginYear = date("Y", $UDateStamp);
                $BeginMonth = date("n", $UDateStamp);
                $BeginDay = date("j", $UDateStamp);
            }
        }

        # if end date value supplied and no end date found and end date value is not illegal
        if (($EndDate != NULL) && !isset($EndYear)
                && ($EndDate != "0000-00-00")
                && ($EndDate != "0000-00-00 00:00:00"))
        {
            # try system call to parse incoming date
            $UDateStamp = strtotime($EndDate);

            # if system call was able to parse date
            if (($UDateStamp != -1) && ($UDateStamp !== FALSE))
            {
                # set begin date to value returned by system call
                $EndYear = date("Y", $UDateStamp);
                $EndMonth = date("n", $UDateStamp);
                $EndDay = date("j", $UDateStamp);
            }
        }

        # if end date is before begin date
        if ((isset($EndYear) && isset($BeginYear) && ($EndYear < $BeginYear))
            || (isset($BeginYear)  && isset($EndYear)  && ($EndYear == $BeginYear) && 
                isset($BeginMonth) && isset($EndMonth) && ($EndMonth < $BeginMonth))
            || (isset($BeginYear)  && isset($EndYear)  && ($EndYear == $BeginYear) && 
                isset($BeginMonth) && isset($EndMonth) && ($EndMonth == $BeginMonth) &&
                isset($BeginDay)   && isset($EndDay)   && ($EndDay < $BeginDay)))
        {
            # swap begin and end dates
            $TempYear = $BeginYear;
            $TempMonth = $BeginMonth;
            $TempDay = $BeginDay;
            $BeginYear = $EndYear;
            $BeginMonth = $EndMonth;
            $BeginDay = $EndDay;
            $EndYear = $TempYear;
            $EndMonth = $TempMonth;
            $EndDay = $TempDay;
        }

        # if precision value supplied by caller
        if ($Precision != NULL)
        {
            # use supplied precision value
            $this->Precision = $Precision;
        }
        else
        {
            # save new precision value
            if (isset($BeginYear)) {  $Prec |= DATEPRE_BEGINYEAR;  }
            if (isset($BeginMonth)) {  $Prec |= DATEPRE_BEGINMONTH;  }
            if (isset($BeginDay)) {  $Prec |= DATEPRE_BEGINDAY;  }
            if (isset($EndYear)) {  $Prec |= DATEPRE_ENDYEAR;  }
            if (isset($EndMonth)) {  $Prec |= DATEPRE_ENDMONTH;  }
            if (isset($EndDay)) {  $Prec |= DATEPRE_ENDDAY;  }
            $this->Precision = $Prec;
        }

        # save new date values
        if ($this->DebugLevel > 1) {  print("Date:  BeginYear = $BeginYear<br>\n");  }
        if ($this->DebugLevel > 1) {  print("Date:  BeginMonth = $BeginMonth<br>\n");  }
        if ($this->DebugLevel > 1) {  print("Date:  BeginDay = $BeginDay<br>\n");  }
        if ($this->DebugLevel > 1) {  print("Date:  EndYear = $EndYear<br>\n");  }
        if ($this->DebugLevel > 1) {  print("Date:  EndMonth = $EndMonth<br>\n");  }
        if ($this->DebugLevel > 1) {  print("Date:  EndDay = $EndDay<br>\n");  }
        if ($this->DebugLevel > 1) {  print("Date:  Precision = ".$this->FormattedPrecision()."<br>\n");  }
        $this->BeginYear  = isset($BeginYear)  ? $BeginYear  : NULL ;
        $this->BeginMonth = isset($BeginMonth) ? $BeginMonth : NULL ;
        $this->BeginDay   = isset($BeginDay)   ? $BeginDay   : NULL ;
        $this->EndYear    = isset($EndYear)    ? $EndYear    : NULL ;
        $this->EndMonth   = isset($EndMonth)   ? $EndMonth   : NULL ;
        $this->EndDay     = isset($EndDay)     ? $EndDay     : NULL ;
    }

    # return value suitable for display
    function Formatted()
    {
        # if begin year available
        $DateString = "";
        if ($this->Precision & DATEPRE_BEGINYEAR)
        {
            # start with begin year
            $DateString = $this->BeginYear;

            # if begin month available
            if ($this->Precision & DATEPRE_BEGINMONTH)
            {
                # add begin month
                $DateString .= "-".$this->BeginMonth;

                # if begin day available
                if ($this->Precision & DATEPRE_BEGINDAY)
                {
                    # add begin day
                    $DateString .= "-".$this->BeginDay;
                }
            }

            # if end year available
            if ($this->Precision & DATEPRE_ENDYEAR)
            {
                # if separate dates
                if ($this->Precision & DATEPRE_SEPARATE)
                {
                    # separate dates with comma
                    $DateString .= ", ";
                }
                else
                {
                    # separate dates with dash
                    $DateString .= " - ";
                }

                # add end year
                $DateString .= $this->EndYear;

                # if end month available
                if ($this->Precision & DATEPRE_ENDMONTH)
                {
                    # add end month
                    $DateString .= "-".$this->EndMonth;

                    # if end day available
                    if ($this->Precision & DATEPRE_ENDDAY)
                    {
                        # add end day
                        $DateString .= "-".$this->EndDay;
                    }
                }
            }
            else
            {
                # if date is open-ended
                if ($this->Precision & DATEPRE_CONTINUOUS)
                {
                    # add dash to indicate open-ended
                    $DateString .= "-";
                }
            }

            # if copyright flag is set
            if ($this->Precision & DATEPRE_COPYRIGHT)
            {
                # add on copyright indicator
                $DateString = "c".$DateString;
            }

            # if flag is set indicating date was inferred
            if ($this->Precision & DATEPRE_INFERRED)
            {
                # add on inferred indicators
                $DateString = "[".$DateString."]";
            }
        }

        # return formatted date string to caller
        return $DateString;
    }

    # return date in format specified like PHP date() format parameter
    function PFormatted($Format, $ReturnEndDate = FALSE)
    {
        if ($ReturnEndDate)
    {
        $Month = ($this->Precision & DATEPRE_ENDMONTH) ? $this->EndMonth : 1;
        $Day = ($this->Precision & DATEPRE_ENDDAY) ? $this->EndDay : 1;
        $Year = ($this->Precision & DATEPRE_ENDYEAR) ? $this->EndYear : 1;
    }
    else
    {
        $Month = ($this->Precision & DATEPRE_BEGINMONTH) ? $this->BeginMonth : 1;
        $Day = ($this->Precision & DATEPRE_BEGINDAY) ? $this->BeginDay : 1;
        $Year = ($this->Precision & DATEPRE_BEGINYEAR) ? $this->BeginYear : 1;
    }
        return date($Format, mktime(0, 0, 0, $Month, $Day, $Year));
    }

    # get begin date/time (or end if requested) formatted for SQL DATETIME field
    function FormattedForSql($ReturnEndDate = FALSE)
    {
        return $this->PFormatted("Y-m-d H:i:s", $ReturnEndDate);
    }

    # return begin time in ISO 8601 format
    function FormattedISO8601()
    {
        # if begin year available
        if ($this->Precision & DATEPRE_BEGINYEAR)
        {
            # start with begin year
            $DateString = sprintf("%04d", $this->BeginYear);

            # if begin month available
            if ($this->Precision & DATEPRE_BEGINMONTH)
            {
                # add begin month
                $DateString .= sprintf("-%02d", $this->BeginMonth);

                # if begin day available
                if ($this->Precision & DATEPRE_BEGINDAY)
                {
                    # add begin day
                    $DateString .= sprintf("-%02d", $this->BeginDay);
                }
            }
        }

        # return ISO 8601 formatted date string to caller
        return $DateString;
    }

    # return values in UTC instead of local time  (NOT IMPLEMENTED)
    function UseUTC()
    {
        # if not currently in UTC
        if ($this->InUTC != TRUE)
        {
            # adjust date to UTC
            # ???

            # set flag to indicate we are in UTC
            $this->InUTC = TRUE;
        }
    }

    # return values in local time instead of UTC  (NOT IMPLEMENTED)
    function UseLocalTime()
    {
        # if currently in UTC
        if ($this->InUTC)
        {
            # adjust date to local time
            # ???

            # set flag to indicate we are in local time
            $this->InUTC = FALSE;
        }
    }

    # return normalized values (suitable for storing via SQL)
    function BeginDate()
    {
        # build date string based on current precision
        if ($this->Precision & DATEPRE_BEGINYEAR)
        {
            if ($this->Precision & DATEPRE_BEGINMONTH)
            {
                if ($this->Precision & DATEPRE_BEGINMONTH)
                {
                    $DateFormat = "%04d-%02d-%02d";
                }
                else
                {
                    $DateFormat = "%04d-%02d-01";
                }
            }
            else
            {
                $DateFormat = "%04d-01-01";
            }

            $DateString = sprintf($DateFormat,
                                  $this->BeginYear, $this->BeginMonth, $this->BeginDay);
        }
        else
        {
            $DateString = NULL;
        }

        # return date string to caller
        return $DateString;
    }
    function EndDate()
    {
        # build date string based on current precision
        if ($this->Precision & DATEPRE_ENDYEAR)
        {
            if ($this->Precision & DATEPRE_ENDMONTH)
            {
                if ($this->Precision & DATEPRE_ENDMONTH)
                {
                    $DateFormat = "%04d-%02d-%02d";
                }
                else
                {
                    $DateFormat = "%04d-%02d-00";
                }
            }
            else
            {
                $DateFormat = "%04d-00-00";
            }

            $DateString = sprintf($DateFormat,
                                  $this->EndYear, $this->EndMonth, $this->EndDay);
        }
        else
        {
            $DateString = NULL;
        }

        # return date string to caller
        return $DateString;
    }

    # get or set precision value (combination of boolean flags)
    function Precision($NewPrecision = NULL)
    {
        if ($NewPrecision != NULL) {  $this->Precision = $NewPrecision;  }
        return $this->Precision;
    }

    # return text of SQL condition for records that match date
    function SqlCondition($FieldName, $EndFieldName = NULL, $Operator = "=")
    {
        # if no date value is set
        if ($this->Precision < 1)
        {
            # if operator is equals
            if ($Operator == "=")
            {
                # construct conditional that will find null dates
                $Condition = "(".$FieldName." IS NULL OR ".$FieldName." < '0000-01-01 00:00:01')";
            }
            else
            {
                # construct conditional that will find non-null dates
                $Condition = "(".$FieldName." > '0000-01-01 00:00:00')";
            }
        }
        else
        {
            # use begin field name as end if no end field specified
            if ($EndFieldName == NULL) {  $EndFieldName = $FieldName;  }

            # determine begin and end of range
            $BeginYear = $this->BeginYear;
            if ($this->Precision & DATEPRE_BEGINMONTH)
            {
                $BeginMonth = $this->BeginMonth;
                if ($this->Precision & DATEPRE_BEGINDAY)
                {
                    $BeginDay = $this->BeginDay - 1;
                }
                else
                {
                    $BeginDay = 0;
                }
            }
            else
            {
                $BeginMonth = 1;
                $BeginDay = 0;
            }
            if ($this->Precision & DATEPRE_ENDYEAR)
            {
                $EndYear = $this->EndYear;
                if ($this->Precision & DATEPRE_ENDMONTH)
                {
                    $EndMonth = $this->EndMonth;
                    if ($this->Precision & DATEPRE_ENDDAY)
                    {
                        $EndDay = $this->EndDay;
                    }
                    else
                    {
                        $EndMonth++;
                        $EndDay = 0;
                    }
                }
                else
                {
                    $EndYear++;
                    $EndMonth = 1;
                    $EndDay = 0;
                }
            }
            else
            {
                $EndYear = $BeginYear;
                if ($this->Precision & DATEPRE_BEGINMONTH)
                {
                    $EndMonth = $BeginMonth;
                    if ($this->Precision & DATEPRE_BEGINDAY)
                    {
                        $EndDay = $BeginDay + 1;
                    }
                    else
                    {
                        $EndMonth++;
                        $EndDay = 0;
                    }
                }
                else
                {
                    $EndYear++;
                    $EndMonth = 1;
                    $EndDay = 0;
                }
            }
            $RangeBegin = "'".date("Y-m-d H:i:s", mktime(23, 59, 59, $BeginMonth, $BeginDay, $BeginYear))."'";
            $RangeEnd = "'".date("Y-m-d H:i:s", mktime(23, 59, 59, $EndMonth, $EndDay, $EndYear))."'";

            # construct SQL condition
            switch ($Operator)
            {
                case ">":
                    $Condition = " ${FieldName} > ${RangeEnd} ";
                    break;

                case ">=":
                    $Condition = " ${FieldName} > ${RangeBegin} ";
                    break;

                case "<":
                    $Condition = " ${FieldName} <= ${RangeBegin} ";
                    break;

                case "<=":
                    $Condition = " ${FieldName} <= ${RangeEnd} ";
                    break;

                case "!=":
                    $Condition = " (${FieldName} <= ${RangeBegin}"
                            ." OR ${FieldName} > ${RangeEnd}) ";
                    break;

                case "=":
                default:
                    $Condition = " (${FieldName} > ${RangeBegin}"
                            ." AND ${FieldName} <= ${RangeEnd}) ";
                    break;
            }
        }

        # return condition to caller
        return $Condition;
    }

    # return string containing printable version of precision flags
    function FormattedPrecision($Precision = NULL)
    {
        if ($Precision === NULL) {  $Precision = $this->Precision;  }
        $String = "";
        if ($Precision & DATEPRE_BEGINYEAR) {  $String .= "| BEGINYEAR ";  }
        if ($Precision & DATEPRE_BEGINMONTH) {  $String .= "| BEGINMONTH ";  }
        if ($Precision & DATEPRE_BEGINDAY) {  $String .= "| BEGINDAY ";  }
        if ($Precision & DATEPRE_BEGINDECADE) {  $String .= "| BEGINDECADE ";  }
        if ($Precision & DATEPRE_ENDYEAR) {  $String .= "| ENDYEAR ";  }
        if ($Precision & DATEPRE_ENDMONTH) {  $String .= "| ENDMONTH ";  }
        if ($Precision & DATEPRE_ENDDAY) {  $String .= "| ENDDAY ";  }
        if ($Precision & DATEPRE_ENDDECADE) {  $String .= "| ENDDECADE ";  }
        if ($Precision & DATEPRE_INFERRED) {  $String .= "| INFERRED ";  }
        if ($Precision & DATEPRE_COPYRIGHT) {  $String .= "| COPYRIGHT ";  }
        if ($Precision & DATEPRE_CONTINUOUS) {  $String .= "| CONTINUOUS ";  }
        if ($Precision & DATEPRE_SEPARATE) {  $String .= "| SEPARATE ";  }
        $String = preg_replace("/^\\|/", "", $String);
        return $String;
    }


    # ---- PRIVATE INTERFACE -------------------------------------------------

    var $BeginDay;
    var $BeginMonth;
    var $BeginYear;
    var $EndDay;
    var $EndMonth;
    var $EndYear;
    var $Precision;
    var $DebugLevel;
    
    # Return the first non-empty parameterized subexpression match
    # Expects a match array from preg_match()
    # Expects a number of array elements, eg. match1, match2, match3
    # Checks each element and returns the first non-empty one
    # If they are all empty, NULL is returned
    private function ExtractMatchData( $Matches, $Member, $Max )
    {
      for( $i=1; $i<=$Max; $i++ )
      {
        if (isset($Matches[$Member.$i]) && strlen($Matches[$Member.$i])>0)
        {
          return $Matches[$Member.$i];
        }
      }
      return NULL;
   }
}

# date precision flags
define("DATEPRE_BEGINYEAR",   1);
define("DATEPRE_BEGINMONTH",  2);
define("DATEPRE_BEGINDAY",    4);
define("DATEPRE_BEGINDECADE", 8);
define("DATEPRE_BEGINCENTURY",16);
define("DATEPRE_ENDYEAR",     32);
define("DATEPRE_ENDMONTH",    64);
define("DATEPRE_ENDDAY",      128);
define("DATEPRE_ENDDECADE",   256);
define("DATEPRE_ENDCENTURY",  512);
define("DATEPRE_INFERRED",    1024);
define("DATEPRE_COPYRIGHT",   2048);
define("DATEPRE_CONTINUOUS",  4096);
define("DATEPRE_SEPARATE",    8192);
define("DATEPRE_UNSURE",      16384);


?>
