"Fossies" - the Fresh Open Source Software Archive

Member "reportlab-3.5.32/src/reportlab/lib/normalDate.py" (1 Oct 2019, 22428 Bytes) of package /linux/privat/reportlab-3.5.32.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "normalDate.py" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.5.23_vs_3.5.26.

    1 #!/usr/bin/env python
    2 # normalDate.py - version 1.0 - 20000717
    3 #hacked by Robin Becker 10/Apr/2001
    4 #major changes include
    5 #   using Types instead of type(0) etc
    6 #   BusinessDate class
    7 #   __radd__, __rsub__ methods
    8 #   formatMS stuff
    9 
   10 # derived from an original version created
   11 # by Jeff Bauer of Rubicon Research and used
   12 # with his kind permission
   13 __version__='3.3.18'
   14 __doc__="Jeff Bauer's lightweight date class, extended by us.  Predates Python's datetime module."
   15 
   16 _bigBangScalar = -4345732  # based on (-9999, 1, 1) BC/BCE minimum
   17 _bigCrunchScalar = 2958463  # based on (9999,12,31) AD/CE maximum
   18 _daysInMonthNormal = [31,28,31,30,31,30,31,31,30,31,30,31]
   19 _daysInMonthLeapYear = [31,29,31,30,31,30,31,31,30,31,30,31]
   20 _dayOfWeekName = '''Monday Tuesday Wednesday Thursday Friday Saturday Sunday'''
   21 _dayOfWeekNameLower = _dayOfWeekName.lower().split()
   22 _dayOfWeekName = _dayOfWeekName.split()
   23 _monthName = '''January February March April May June
   24                 July August September October November December'''
   25 _monthNameLower = _monthName.lower().split()
   26 _monthNameLower = _monthName.split()
   27 
   28 from reportlab import cmp
   29 import re, time, datetime
   30 from .utils import isPy3, isStr
   31 
   32 if hasattr(time,'struct_time'):
   33     _DateSeqTypes = (list,tuple,time.struct_time)
   34 else:
   35     _DateSeqTypes = (list,tuple)
   36 
   37 _fmtPat = re.compile('\\{(m{1,5}|yyyy|yy|d{1,4})\\}',re.MULTILINE|re.IGNORECASE)
   38 _iso_re = re.compile(r'(\d\d\d\d|\d\d)-(\d\d)-(\d\d)')
   39 
   40 def getStdMonthNames():
   41     return _monthNameLower
   42 
   43 def getStdShortMonthNames():
   44     return [x[:3] for x in getStdMonthNames()]
   45 
   46 def getStdDayNames():
   47     return _dayOfWeekNameLower
   48 
   49 def getStdShortDayNames():
   50     return [x[:3] for x in getStdDayNames()]
   51 
   52 def isLeapYear(year):
   53     """determine if specified year is leap year, returns Python boolean"""
   54     if year < 1600:
   55         if year % 4:
   56             return 0
   57         else:
   58             return 1
   59     elif year % 4 != 0:
   60         return 0
   61     elif year % 100 != 0:
   62         return 1
   63     elif year % 400 != 0:
   64         return 0
   65     else:
   66         return 1
   67 
   68 class NormalDateException(Exception):
   69     """Exception class for NormalDate"""
   70     pass
   71 
   72 class NormalDate:
   73     """
   74     NormalDate is a specialized class to handle dates without
   75     all the excess baggage (time zones, daylight savings, leap
   76     seconds, etc.) of other date structures.  The minimalist
   77     strategy greatly simplifies its implementation and use.
   78 
   79     Internally, NormalDate is stored as an integer with values
   80     in a discontinuous range of -99990101 to 99991231.  The
   81     integer value is used principally for storage and to simplify
   82     the user interface.  Internal calculations are performed by
   83     a scalar based on Jan 1, 1900.
   84 
   85     Valid NormalDate ranges include (-9999,1,1) B.C.E. through
   86     (9999,12,31) C.E./A.D.
   87 
   88 
   89     1.0
   90         No changes, except the version number.  After 3 years of use by
   91         various parties I think we can consider it stable.
   92 
   93     0.8
   94         Added Prof. Stephen Walton's suggestion for a range method
   95          - module author resisted the temptation to use lambda <0.5 wink>
   96 
   97     0.7
   98         Added Dan Winkler's suggestions for __add__, __sub__ methods
   99 
  100     0.6
  101         Modifications suggested by Kevin Digweed to fix:
  102          - dayOfWeek, dayOfWeekAbbrev, clone methods
  103          - Permit NormalDate to be a better behaved superclass
  104 
  105     0.5
  106         Minor tweaking
  107 
  108     0.4
  109          - Added methods __cmp__, __hash__
  110          - Added Epoch variable, scoped to the module
  111          - Added setDay, setMonth, setYear methods
  112 
  113     0.3
  114         Minor touch-ups
  115 
  116     0.2
  117          - Fixed bug for certain B.C.E leap years
  118          - Added Jim Fulton's suggestions for short alias class name =ND
  119            and __getstate__, __setstate__ methods
  120 
  121     Special thanks:  Roedy Green
  122     """
  123     def __init__(self, normalDate=None):
  124         """
  125         Accept 1 of 4 values to initialize a NormalDate:
  126             1. None - creates a NormalDate for the current day
  127             2. integer in yyyymmdd format
  128             3. string in yyyymmdd format
  129             4. tuple in (yyyy, mm, dd) - localtime/gmtime can also be used
  130             5. string iso date format see _iso_re above
  131             6. datetime.datetime or datetime.date
  132         """
  133         if normalDate is None:
  134             self.setNormalDate(time.localtime(time.time()))
  135         else:
  136             self.setNormalDate(normalDate)
  137 
  138     def add(self, days):
  139         """add days to date; use negative integers to subtract"""
  140         if not isinstance(days,int):
  141             raise NormalDateException( \
  142                 'add method parameter must be integer type')
  143         self.normalize(self.scalar() + days)
  144 
  145     def __add__(self, days):
  146         """add integer to normalDate and return a new, calculated value"""
  147         if not isinstance(days,int):
  148             raise NormalDateException( \
  149                 '__add__ parameter must be integer type')
  150         cloned = self.clone()
  151         cloned.add(days)
  152         return cloned
  153 
  154     def __radd__(self,days):
  155         '''for completeness'''
  156         return self.__add__(days)
  157 
  158     def clone(self):
  159         """return a cloned instance of this normalDate"""
  160         return self.__class__(self.normalDate)
  161 
  162     if not isPy3:
  163         def __cmp__(self, target):
  164             if target is None:
  165                 return 1
  166             elif not hasattr(target, 'normalDate'):
  167                 return 1
  168             else:
  169                 return cmp(self.normalDate, target.normalDate)
  170     else:
  171         def __lt__(self,other):
  172             if not hasattr(other,'normalDate'):
  173                 return False
  174             return self.normalDate < other.normalDate
  175 
  176         def __le__(self,other):
  177             if not hasattr(other,'normalDate'):
  178                 return False
  179             return self.normalDate <= other.normalDate
  180 
  181         def __eq__(self,other):
  182             if not hasattr(other,'normalDate'):
  183                 return False
  184             return self.normalDate == other.normalDate
  185 
  186         def __ne__(self,other):
  187             if not hasattr(other,'normalDate'):
  188                 return True
  189             return self.normalDate != other.normalDate
  190 
  191         def __ge__(self,other):
  192             if not hasattr(other,'normalDate'):
  193                 return True
  194             return self.normalDate >= other.normalDate
  195 
  196         def __gt__(self,other):
  197             if not hasattr(other,'normalDate'):
  198                 return True
  199             return self.normalDate > other.normalDate
  200 
  201     def day(self):
  202         """return the day as integer 1-31"""
  203         return int(repr(self.normalDate)[-2:])
  204 
  205     def dayOfWeek(self):
  206         """return integer representing day of week, Mon=0, Tue=1, etc."""
  207         return dayOfWeek(*self.toTuple())
  208 
  209     @property
  210     def __day_of_week_name__(self):
  211         return getattr(self,'_dayOfWeekName',_dayOfWeekName)
  212 
  213     def dayOfWeekAbbrev(self):
  214         """return day of week abbreviation for current date: Mon, Tue, etc."""
  215         return self.__day_of_week_name__[self.dayOfWeek()][:3]
  216 
  217     def dayOfWeekName(self):
  218         """return day of week name for current date: Monday, Tuesday, etc."""
  219         return self.__day_of_week_name__[self.dayOfWeek()]
  220 
  221     def dayOfYear(self):
  222         """day of year"""
  223         if self.isLeapYear():
  224             daysByMonth = _daysInMonthLeapYear
  225         else:
  226             daysByMonth = _daysInMonthNormal
  227         priorMonthDays = 0
  228         for m in range(self.month() - 1):
  229             priorMonthDays = priorMonthDays + daysByMonth[m]
  230         return self.day() + priorMonthDays
  231 
  232     def daysBetweenDates(self, normalDate):
  233         """
  234         return value may be negative, since calculation is
  235         self.scalar() - arg
  236         """
  237         if isinstance(normalDate,NormalDate):
  238             return self.scalar() - normalDate.scalar()
  239         else:
  240             return self.scalar() - NormalDate(normalDate).scalar()
  241 
  242     def equals(self, target):
  243         if isinstance(target,NormalDate):
  244             if target is None:
  245                 return self.normalDate is None
  246             else:
  247                 return self.normalDate == target.normalDate
  248         else:
  249             return 0
  250 
  251     def endOfMonth(self):
  252         """returns (cloned) last day of month"""
  253         return self.__class__(self.__repr__()[-8:-2]+str(self.lastDayOfMonth()))
  254 
  255     def firstDayOfMonth(self):
  256         """returns (cloned) first day of month"""
  257         return self.__class__(self.__repr__()[-8:-2]+"01")
  258 
  259     def formatUS(self):
  260         """return date as string in common US format: MM/DD/YY"""
  261         d = self.__repr__()
  262         return "%s/%s/%s" % (d[-4:-2], d[-2:], d[-6:-4])
  263 
  264     def formatUSCentury(self):
  265         """return date as string in 4-digit year US format: MM/DD/YYYY"""
  266         d = self.__repr__()
  267         return "%s/%s/%s" % (d[-4:-2], d[-2:], d[-8:-4])
  268 
  269     def _fmtM(self):
  270         return str(self.month())
  271 
  272     def _fmtMM(self):
  273         return '%02d' % self.month()
  274 
  275     def _fmtMMM(self):
  276         return self.monthAbbrev()
  277 
  278     def _fmtMMMM(self):
  279         return self.monthName()
  280 
  281     def _fmtMMMMM(self):
  282         return self.monthName()[0]
  283 
  284     def _fmtD(self):
  285         return str(self.day())
  286 
  287     def _fmtDD(self):
  288         return '%02d' % self.day()
  289 
  290     def _fmtDDD(self):
  291         return self.dayOfWeekAbbrev()
  292 
  293     def _fmtDDDD(self):
  294         return self.dayOfWeekName()
  295 
  296     def _fmtYY(self):
  297         return '%02d' % (self.year()%100)
  298 
  299     def _fmtYYYY(self):
  300         return str(self.year())
  301 
  302     def formatMS(self,fmt):
  303         '''format like MS date using the notation
  304         {YY}    --> 2 digit year
  305         {YYYY}  --> 4 digit year
  306         {M}     --> month as digit
  307         {MM}    --> 2 digit month
  308         {MMM}   --> abbreviated month name
  309         {MMMM}  --> monthname
  310         {MMMMM} --> first character of monthname
  311         {D}     --> day of month as digit
  312         {DD}    --> 2 digit day of month
  313         {DDD}   --> abrreviated weekday name
  314         {DDDD}  --> weekday name
  315         '''
  316         r = fmt[:]
  317         f = 0
  318         while 1:
  319             m = _fmtPat.search(r,f)
  320             if m:
  321                 y = getattr(self,'_fmt'+(m.group()[1:-1].upper()))()
  322                 i, j = m.span()
  323                 r = (r[0:i] + y) + r[j:]
  324                 f = i + len(y)
  325             else:
  326                 return r
  327 
  328     def __getstate__(self):
  329         """minimize persistent storage requirements"""
  330         return self.normalDate
  331 
  332     def __hash__(self):
  333         return hash(self.normalDate)
  334 
  335     def __int__(self):
  336         return self.normalDate
  337 
  338     def isLeapYear(self):
  339         """
  340         determine if specified year is leap year, returning true (1) or
  341         false (0)
  342         """
  343         return isLeapYear(self.year())
  344 
  345     def _isValidNormalDate(self, normalDate):
  346         """checks for date validity in [-]yyyymmdd format"""
  347         if not isinstance(normalDate,int):
  348             return 0
  349         if len(repr(normalDate)) > 9:
  350             return 0
  351         if normalDate < 0:
  352             dateStr = "%09d" % normalDate
  353         else:
  354             dateStr = "%08d" % normalDate
  355         if len(dateStr) < 8:
  356             return 0
  357         elif len(dateStr) == 9:
  358             if (dateStr[0] != '-' and dateStr[0] != '+'):
  359                 return 0
  360         year = int(dateStr[:-4])
  361         if year < -9999 or year > 9999 or year == 0:
  362             return 0    # note: zero (0) is not a valid year
  363         month = int(dateStr[-4:-2])
  364         if month < 1 or month > 12:
  365             return 0
  366         if isLeapYear(year):
  367             maxDay = _daysInMonthLeapYear[month - 1]
  368         else:
  369             maxDay = _daysInMonthNormal[month - 1]
  370         day = int(dateStr[-2:])
  371         if day < 1 or day > maxDay:
  372             return 0
  373         if year == 1582 and month == 10 and day > 4 and day < 15:
  374             return 0  # special case of 10 days dropped: Oct 5-14, 1582
  375         return 1
  376 
  377     def lastDayOfMonth(self):
  378         """returns last day of the month as integer 28-31"""
  379         if self.isLeapYear():
  380             return _daysInMonthLeapYear[self.month() - 1]
  381         else:
  382             return _daysInMonthNormal[self.month() - 1]
  383 
  384     def localeFormat(self):
  385         """override this method to use your preferred locale format"""
  386         return self.formatUS()
  387 
  388     def month(self):
  389         """returns month as integer 1-12"""
  390         return int(repr(self.normalDate)[-4:-2])
  391     
  392     @property
  393     def __month_name__(self):
  394         return getattr(self,'_monthName',_monthName)
  395 
  396     def monthAbbrev(self):
  397         """returns month as a 3-character abbreviation, i.e. Jan, Feb, etc."""
  398         return self.__month_name__[self.month() - 1][:3]
  399 
  400     def monthName(self):
  401         """returns month name, i.e. January, February, etc."""
  402         return self.__month_name__[self.month() - 1]
  403 
  404     def normalize(self, scalar):
  405         """convert scalar to normalDate"""
  406         if scalar < _bigBangScalar:
  407             msg = "normalize(%d): scalar below minimum" % \
  408                   _bigBangScalar
  409             raise NormalDateException(msg)
  410         if scalar > _bigCrunchScalar:
  411             msg = "normalize(%d): scalar exceeds maximum" % \
  412                   _bigCrunchScalar
  413             raise NormalDateException(msg)
  414         from math import floor
  415         if scalar >= -115860:
  416             year = 1600 + int(floor((scalar + 109573) / 365.2425))
  417         elif scalar >= -693597:
  418             year = 4 + int(floor((scalar + 692502) / 365.2425))
  419         else:
  420             year = -4 + int(floor((scalar + 695058) / 365.2425))
  421         days = scalar - firstDayOfYear(year) + 1
  422         if days <= 0:
  423             year = year - 1
  424             days = scalar - firstDayOfYear(year) + 1
  425         daysInYear = 365
  426         if isLeapYear(year):
  427             daysInYear = daysInYear + 1
  428         if days > daysInYear:
  429             year = year + 1
  430             days = scalar - firstDayOfYear(year) + 1
  431         # add 10 days if between Oct 15, 1582 and Dec 31, 1582
  432         if (scalar >= -115860 and scalar <= -115783):
  433             days = days + 10
  434         if isLeapYear(year):
  435             daysByMonth = _daysInMonthLeapYear
  436         else:
  437             daysByMonth = _daysInMonthNormal
  438         dc = 0; month = 12
  439         for m in range(len(daysByMonth)):
  440             dc = dc + daysByMonth[m]
  441             if dc >= days:
  442                 month = m + 1
  443                 break
  444         # add up the days in prior months
  445         priorMonthDays = 0
  446         for m in range(month - 1):
  447             priorMonthDays = priorMonthDays + daysByMonth[m]
  448         day = days - priorMonthDays
  449         self.setNormalDate((year, month, day))
  450 
  451     def range(self, days):
  452         """Return a range of normalDates as a list.  Parameter
  453         may be an int or normalDate."""
  454         if not isinstance(days,int):
  455             days = days - self  # if not int, assume arg is normalDate type
  456         r = []
  457         for i in range(days):
  458             r.append(self + i)
  459         return r
  460 
  461     def __repr__(self):
  462         """print format: [-]yyyymmdd"""
  463         # Note: When disassembling a NormalDate string, be sure to
  464         # count from the right, i.e. epochMonth = int(repr(Epoch)[-4:-2]),
  465         # or the slice won't work for dates B.C.
  466         if self.normalDate < 0:
  467             return "%09d" % self.normalDate
  468         else:
  469             return "%08d" % self.normalDate
  470 
  471     def scalar(self):
  472         """days since baseline date: Jan 1, 1900"""
  473         (year, month, day) = self.toTuple()
  474         days = firstDayOfYear(year) + day - 1
  475         if self.isLeapYear():
  476             for m in range(month - 1):
  477                 days = days + _daysInMonthLeapYear[m]
  478         else:
  479             for m in range(month - 1):
  480                 days = days + _daysInMonthNormal[m]
  481         if year == 1582:
  482             if month > 10 or (month == 10 and day > 4):
  483                 days = days - 10
  484         return days
  485 
  486     def setDay(self, day):
  487         """set the day of the month"""
  488         maxDay = self.lastDayOfMonth()
  489         if day < 1 or day > maxDay:
  490             msg = "day is outside of range 1 to %d" % maxDay
  491             raise NormalDateException(msg)
  492         (y, m, d) = self.toTuple()
  493         self.setNormalDate((y, m, day))
  494 
  495     def setMonth(self, month):
  496         """set the month [1-12]"""
  497         if month < 1 or month > 12:
  498             raise NormalDateException('month is outside range 1 to 12')
  499         (y, m, d) = self.toTuple()
  500         self.setNormalDate((y, month, d))
  501 
  502     def setNormalDate(self, normalDate):
  503         """
  504         accepts date as scalar string/integer (yyyymmdd) or tuple
  505         (year, month, day, ...)"""
  506         if isinstance(normalDate,int):
  507             self.normalDate = normalDate
  508         elif isStr(normalDate):
  509             try:
  510                 self.normalDate = int(normalDate)
  511             except:
  512                 m = _iso_re.match(normalDate)
  513                 if m:
  514                     self.setNormalDate(m.group(1)+m.group(2)+m.group(3))
  515                 else:
  516                     raise NormalDateException("unable to setNormalDate(%s)" % repr(normalDate))
  517         elif isinstance(normalDate,_DateSeqTypes):
  518             self.normalDate = int("%04d%02d%02d" % normalDate[:3])
  519         elif isinstance(normalDate,NormalDate):
  520             self.normalDate = normalDate.normalDate
  521         elif isinstance(normalDate,(datetime.datetime,datetime.date)):
  522             self.normalDate = (normalDate.year*100+normalDate.month)*100+normalDate.day
  523         else:
  524             self.normalDate = None
  525         if not self._isValidNormalDate(self.normalDate):
  526             raise NormalDateException("unable to setNormalDate(%s)" % repr(normalDate))
  527 
  528     def setYear(self, year):
  529         if year == 0:
  530             raise NormalDateException('cannot set year to zero')
  531         elif year < -9999:
  532             raise NormalDateException('year cannot be less than -9999')
  533         elif year > 9999:
  534             raise NormalDateException('year cannot be greater than 9999')
  535         (y, m, d) = self.toTuple()
  536         self.setNormalDate((year, m, d))
  537 
  538     __setstate__ = setNormalDate
  539 
  540     def __sub__(self, v):
  541         if isinstance(v,int):
  542             return self.__add__(-v)
  543         return self.scalar() - v.scalar()
  544 
  545     def __rsub__(self,v):
  546         if isinstance(v,int):
  547             return NormalDate(v) - self
  548         else:
  549             return v.scalar() - self.scalar()
  550 
  551     def toTuple(self):
  552         """return date as (year, month, day) tuple"""
  553         return (self.year(), self.month(), self.day())
  554 
  555     def year(self):
  556         """return year in yyyy format, negative values indicate B.C."""
  557         return int(repr(self.normalDate)[:-4])
  558 
  559 #################  Utility functions  #################
  560 
  561 def bigBang():
  562     """return lower boundary as a NormalDate"""
  563     return NormalDate((-9999, 1, 1))
  564 
  565 def bigCrunch():
  566     """return upper boundary as a NormalDate"""
  567     return NormalDate((9999, 12, 31))
  568 
  569 def dayOfWeek(y, m, d):
  570     """return integer representing day of week, Mon=0, Tue=1, etc."""
  571     if m == 1 or m == 2:
  572         m = m + 12
  573         y = y - 1
  574     return (d + 2*m + 3*(m+1)//5 + y + y//4 - y//100 + y//400) % 7
  575 
  576 def firstDayOfYear(year):
  577     """number of days to the first of the year, relative to Jan 1, 1900"""
  578     if not isinstance(year,int):
  579         msg = "firstDayOfYear() expected integer, got %s" % type(year)
  580         raise NormalDateException(msg)
  581     if year == 0:
  582         raise NormalDateException('first day of year cannot be zero (0)')
  583     elif year < 0:  # BCE calculation
  584         firstDay = (year * 365) + int((year - 1) / 4) - 693596
  585     else:           # CE calculation
  586         leapAdjust = int((year + 3) / 4)
  587         if year > 1600:
  588             leapAdjust = leapAdjust - int((year + 99 - 1600) / 100) + \
  589                          int((year + 399 - 1600) / 400)
  590         firstDay = year * 365 + leapAdjust - 693963
  591         if year > 1582:
  592             firstDay = firstDay - 10
  593     return firstDay
  594 
  595 def FND(d):
  596     '''convert to ND if required'''
  597     return isinstance(d,NormalDate) and d or ND(d)
  598 
  599 Epoch=bigBang()
  600 ND=NormalDate
  601 BDEpoch=ND(15821018)
  602 BDEpochScalar = -115857
  603 
  604 class BusinessDate(NormalDate):
  605     """
  606     Specialised NormalDate
  607     """
  608     def add(self, days):
  609         """add days to date; use negative integers to subtract"""
  610         if not isinstance(days,int):
  611             raise NormalDateException('add method parameter must be integer')
  612         self.normalize(self.scalar() + days)
  613 
  614     def __add__(self, days):
  615         """add integer to BusinessDate and return a new, calculated value"""
  616         if not isinstance(days,int):
  617             raise NormalDateException('__add__ parameter must be integer')
  618         cloned = self.clone()
  619         cloned.add(days)
  620         return cloned
  621 
  622     def __sub__(self, v):
  623         return isinstance(v,int) and self.__add__(-v) or self.scalar() - v.scalar()
  624 
  625     def asNormalDate(self):
  626         return ND(self.normalDate)
  627 
  628     def daysBetweenDates(self, normalDate):
  629         return self.asNormalDate.daysBetweenDates(normalDate)
  630 
  631     def _checkDOW(self):
  632         if self.dayOfWeek()>4: raise NormalDateException("%r isn't a business day" % self.normalDate)
  633 
  634     def normalize(self, i):
  635         i = int(i)
  636         NormalDate.normalize(self,(i//5)*7+i%5+BDEpochScalar)
  637 
  638     def scalar(self):
  639         d = self.asNormalDate()
  640         i = d - BDEpoch     #luckily BDEpoch is a Monday so we don't have a problem
  641                             #concerning the relative weekday
  642         return 5*(i//7) + i%7
  643 
  644     def setNormalDate(self, normalDate):
  645         NormalDate.setNormalDate(self,normalDate)
  646         self._checkDOW()
  647 
  648 if __name__ == '__main__':
  649     today = NormalDate()
  650     print("NormalDate test:")
  651     print("  Today (%s) is: %s %s" % (today, today.dayOfWeekAbbrev(), today.localeFormat()))
  652     yesterday = today - 1
  653     print("  Yesterday was: %s %s" % (yesterday.dayOfWeekAbbrev(), yesterday.localeFormat()))
  654     tomorrow = today + 1
  655     print("  Tomorrow will be: %s %s" % (tomorrow.dayOfWeekAbbrev(), tomorrow.localeFormat()))
  656     print("  Days between tomorrow and yesterday: %d" % (tomorrow - yesterday))
  657     print(today.formatMS('{d}/{m}/{yy}'))
  658     print(today.formatMS('{dd}/{m}/{yy}'))
  659     print(today.formatMS('{ddd} {d}/{m}/{yy}'))
  660     print(today.formatMS('{dddd} {d}/{m}/{yy}'))
  661     print(today.formatMS('{d}/{mm}/{yy}'))
  662     print(today.formatMS('{d}/{mmm}/{yy}'))
  663     print(today.formatMS('{d}/{mmmm}/{yy}'))
  664     print(today.formatMS('{d}/{m}/{yyyy}'))
  665     b = BusinessDate('20010116')
  666     print('b=',b,'b.scalar()', b.scalar())