BasicDateTime.py :  » Web-Frameworks » Webware » Webware-1.0.2 » MiscUtils » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Webware 
Webware » Webware 1.0.2 » MiscUtils » BasicDateTime.py
"""Date and time classes.

Taken from http://www.pythonweb.org (Web Modules).

By default importing this module imports the Python > 2.3 datetime classes.
Otherwise the less powerful and robust lemon ones are used.

This module is really just meant to be the minimum date implementation that
can be got away with to enable lemon to work with Python < 2.3.

Documentation
-------------

See the Python 2.3 datetime module for documentation on the time, date and
datetime classes. WARNING: These versions do not properly check to make sure
the date you specified is valid.

now() returns the current date and time as a datetime object.

isodatetime2tuple(sql), isotime2tuple(sql) and isodate2tuple(sql) take a
standard isoformat string as would be returned from an sql query and return
the appropriate date or time object. WARNING: Parts of seconds are ignored.

calendar.weekday may break for certain old times. Not sure why, but that is
why it was all fixed in Python 2.3.

"""

import time as t
import calendar
from types import InstanceType

MINYEAR = 1
MAXYEAR = 9999


class DaysInMonth:
  """Simple class to correctly calculate the days in a month in Python 2.2.

  The calendar.monthrange(year, month) fails in that version.

  """

  def calculate(self, year, month):
    return (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)[month] \
      + (month == 2 and self.isleap(year))

  def isleap(self, year):
    """Return 1 for leap years, 0 for non-leap years."""
    return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)

  def test(self):
    passed = 1
    for year in range (1, 9999):
      for month in range(1, 12):
        if DaysInMonth().calculate(year, month) != calendar.monthrange(year, month)[1]:
          print "Failed on %s-%s." % (year, month)
          passed = 0
    if not passed:
      print "FAILED"
    else:
      print "PASSED"
    return passed

  def weekday(self, year, month, day):
    """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12), day (1-31)."""
    secs = t.mktime((year, month, day, 0, 0, 0, 0, 0, 0))
    tuple = t.localtime(secs)
    return tuple[6]

daysInMonth = DaysInMonth()


class datetime:
  """DateTime(year, month=1, day=1, hour=0, minute=0, second=0.0)

  Constructs a DateTime instance from the given values.
  Assumes that the date is given in the Gregorian calendar
  (which it the one used in many countries today).

    WARNING:    Only very limited error checking is done for this class.
          The tuples are filled with the parameters from the last three numbers
          in the current time tuple so only use the first six!!

    Variable ranges:
      MINYEAR 1
      MAXYEAT 9999

      year    MINYEAR-MAXYEAR
      month   1-12
      day     1-31
      hour    0-23
      minute     0-59
      second     0-59  Apparantly it is possible to have a double leap second in Python.
               However, to maintain compatibility with databases, this isn't allowed.

    WARNING:    Seconds are rounded to two decimal places.

  """

  def __init__(self, year, month, day, hour=0, minute=0, second=0, microsecond=0):
    """Initialize datetime object.

    All arguments are integers except second which can be a float.

      WARNING:  Possible problems with months with more days in than they actually have.

    """

    dates = ('year', 'month', 'day', 'hour', 'minute')
    counter = 0
    for item in (year, month, day, hour, minute):
      if type(item) not in (type(1), type(1L)):
        raise TypeError("The variable '%s' should be an integer."
          % dates[counter])
      counter += 1

    if type(second) not in (type(1), type(1L)): # and type(second) != type(1.1)
      raise ValueError("The variable 'second' should be an Integer or a Long.") # or a float

    # Very basic error checking and initialisation.
    if not MINYEAR <= year <= MAXYEAR:
      raise ValueError('The year value must be between %s and %s inclusive.'
        % (MINYEAR, MAXYEAR))
    else:
      self.year = year
    if not 1 <= month < 1 <= 12:
      raise ValueError('The month value must be between 1 and 12 inclusive.')
    else:
      self.month = month
    if not 1 <= day <= daysInMonth.calculate(year, month):
      raise ValueError('The day value must be between 1 and %s inclusive.'
        % daysInMonth.calculate(year, month))
    else:
      self.day = day
    if not 0 <= hour < 24:
      raise ValueError('The hour value must be between 0 and 23 inclusive.')
    else:
      self.hour = hour
    if not 0 <= minute < 60:
      raise ValueError('The minutes value must be between 0 and 59 inclusive.')
    else:
      self.minute = minute
    if not 0 <= second < 60:
      raise ValueError('The seconds value must be between 0 and 59 inclusive.')
    else:
      self.second = second
    if not 0 <= microsecond < 1000000:
      raise ValueError('The microseconds value must be between 0 and 999999 inclusive.')
    else:
      self.microsecond = microsecond

  def now(self):
    """Return the current date and time as a datetime."""
    now = t.localtime()
    return datetime(now[0], now[1], now[2], now[3], now[4], now[5])


  ## Comparison Operators ##

  def _compareDate(self, other):
    if self.year == other.year:
      if self.month == other.month:
        if self.day == other.day:
          return 0
        elif self.day > other.day:
          return 1
        else:
          return -1
      elif self.month > other.month:
        return 1
      else:
        return -1
    elif self.year > other.year:
      return 1
    else:
      return -1

  def _compareTime(self, other):
    if self.hour == other.hour:
      if self.minute == other.minute:
        if self.second == other.second:
          return 0
        elif self.second > other.second:
          return 1
        else:
          return -1
      elif self.minute > other.minute:
        return 1
      else:
        return -1
    elif self.hour > other.hour:
      return 1
    else:
      return -1

  def __cmp__(self, other):
    if type(other) is type(None):
      raise Exception('This comparison is not supported')
    elif type(other) is InstanceType:
      if other.__class__.__name__ == self.__class__.__name__:
        if other.__class__.__name__ == 'date':
          return self._compareDate(other)
        elif other.__class__.__name__ == 'time':
          return self._compareTime(other)
        elif other.__class__.__name__ == 'datetime':
          date = self._compareDate(other)
          if date == 0:
            return self._compareTime(other)
          else:
            return date
        else:
          raise Exception('This comparison is not supported')
      else:
        raise Exception('This comparison is not supported')
    else:
      raise Exception('This comparison is not supported')

  def __eq__(self, other):
    if type(other) is InstanceType:
      if other.__class__.__name__ == self.__class__.__name__:
        if other.__class__.__name__ == 'date':
          if self._compareDate(other) == 0:
            return 1
          else:
            return 0
        elif other.__class__.__name__ == 'time':
          if self._compareTime(other) == 0:
            return 1
          else:
            return 0
        elif other.__class__.__name__ == 'datetime':
          date = self._compareDate(other)
          if date == 0:
            if self._compareTime(other) == 0:
              return 1
            else:
              return 0
          else:
            return 0
        else:
          return 0
      else:
        return 0
    else:
      return 0

  def __ne__(self, other):
    if self.__eq__(other):
      return 0
    else:
      return 1

  def __str__(self):
    """Return the object as standard SQL."""
    return self.isoformat()

  def __repr__(self):
    """Return a string representation of the object."""
    return "datetime.datetime(%s, %s, %s, %s, %s, %s)" % (
      self.year, self.month, self.day, self.hour, self.minute, self.second)

  def __getitem__(self, item):
    """Enable dictionary-style attribute reading for year, month, day, hour, minute and second."""
    if item == 'year':
      return self.year
    elif item == 'month':
      return self.month
    elif item == 'day':
      return self.day
    elif item == 'hour':
      return self.hour
    elif item == 'minute':
      return self.minute
    elif item == 'second':
      return self.second
    else:
      raise KeyError("'%s' is not a valid attribute for a Date class." % item)


  ## Formatting ##

  def _addZeros(self, num, s):
    """Private function to add an appropriate number of zeros to s such that len(s) is num."""
    s = str(s)
    while len(s) < num:
      s = '0' + s
    return s

  def _isodate(self):
    """Return the date as a standard SQL string of the format 'YYYY-MM-DD'."""
    return (str(self._addZeros(4, self.year))
      + "-" + str(self._addZeros(2, self.month))
      + "-" + str(self._addZeros(2, self.day)))

  def _isotime(self):
    """Return the time as a standard SQL string in the format 'HH:MM::SS.ss'."""
    return (str(self._addZeros(2, self.hour))
      + ":" + str(self._addZeros(2, self.minute))
      + ":" + str(self._addZeros(2, self.second)))

  def strftime(self, format):
    """Format the time using standard time module string format strings.

      %a Locale's abbreviated weekday name.
      %A Locale's full weekday name.
      %b Locale's abbreviated month name.
      %B Locale's full month name.
      %c Locale's appropriate date and time representation.
      %d Day of the month as a decimal number [01, 31].
      %H Hour (24-hour clock) as a decimal number [00, 23].
      %I Hour (12-hour clock) as a decimal number [01, 12].
      %j Day of the year as a decimal number [001, 366].
      %m Month as a decimal number [01, 12].
      %M Minute as a decimal number [00, 59].
      %p Locale's equivalent of either AM or PM.
      %S Second as a decimal number [00, 61]. (1)
      %U Week number of the year (Sunday as the first day of the week)
        as a decimal number [00, 53]. All days in a new year preceding
        the first Sunday are considered to be in week 0.
      %w Weekday as a decimal number [0(Sunday), 6].
      %W Week number of the year (Monday as the first day of the week)
        as a decimal number [00, 53]. All days in a new year preceding
        the first Monday are considered to be in week 0.
      %x Locale's appropriate date representation.
      %X Locale's appropriate time representation.
      %y Year without century as a decimal number [00, 99].
      %Y Year with century as a decimal number.
      %Z Time zone name (no characters if no time zone exists).
      %% A literal "%" character.
    """
    return t.strftime(format, self.timetuple())


  ## Conversion ##

  def timetuple(self):
    """Return the date and time as a python tuple as constructed by time.localtime().

    WARNING: The last 3 entries in the tuple are obtained from time.localtime()
    and do not represent anything.

    """
    sql =  self.isoformat()
    wday = calendar.weekday(int(sql[0:4]), int(sql[5:7]), int(sql[8:10]))
    return (int(sql[0:4]), int(sql[5:7]), int(sql[8:10]), int(sql[11:13]),
      int(sql[14:16]), int(sql[17:19]), wday, 0, -1)

  def isoformat(self):
    """Return the date and time as a standard SQL string of the format 'YYYY-MM-DD HH:MM:SS.ss'."""
    return self._isodate() + ' ' + self._isotime()


class date(datetime):
  """Constructs an object holding a date value.

  Is just another name binding for DateTime().
  The time part is set to '00:00:00.00'.

  """

  def __init__(self, year, month, day):

    dates = ('year', 'month', 'day')
    counter = 0
    for item in (year, month, day):
      if type(item) not in (type(1), type(1L)):
        raise TypeError("The variable '%s' should be an Integer or a Long."
          % dates[counter])
      counter += 1

    # Very basic error checking and initialisation.
    if not MINYEAR <= year <= MAXYEAR:
      raise ValueError('The year value must be between %s and %s inclusive.'
        % (MINYEAR, MAXYEAR))
    else:
      self.year = year
    if not 1 <= month < 12:
      raise ValueError('The month value must be between 1 and 12 inclusive.')
    else:
      self.month = month
    if not 1 <= day <= daysInMonth.calculate(year, month):
      raise ValueError('The day value must be between 1 and %s inclusive.'
        % daysInMonth.calculate(year, month))
    else:
      self.day = day

  def __repr__(self):
    """Return a string representation of the object."""
    return "datetime.date(%s, %s, %s)" % (self.year, self.month, self.day)

  def isoformat(self):
    """Return the date as a standard SQL string of the format 'YYYY-MM-DD'."""
    return self._isodate()

  def timetuple(self):
    """Returns the date as a python tuple as constructed by time.localtime().

    WARNING: The last 6 entries in the tuple are obtained from time.localtime()
    and do not represent anything.

    """
    sql = self.isoformat()
    wday = calendar.weekday(int(sql[0:4]), int(sql[5:7]), int(sql[8:10]))
    return int(sql[0:4]), int(sql[5:7]), int(sql[8:10]), 0, 0, 0, wday, 0, -1

  def now(self):
    """Return the current date and time as a datetime."""
    now = t.localtime()
    return date(now[0], now[1], now[2])


class time(datetime):
  """Construct an object holding a time value.

  Is just another name binding for DateTime().
  The date part is set to '2000-01-01'.

  """

  def __init__(self, hour=0, minute=0, second=0, microsecond=0):

    dates = ('hour', 'minute')
    counter = 0
    for item in (hour, minute):
      if type(item) not in (type(1), type(1L)):
        raise TypeError("The variable '%s' should be an Integer or a Long."
          % dates[counter])
      counter += 1

    if type(second) != type(1): # and type(second) != type(1.1):
      raise ValueError("The variable 'second' should be an integer.") # or a float

    # Very basic error checking and initialisation.

    if not 0 <= hour < 24:
      raise ValueError('The hour value must be between 0 and 23 inclusive.')
    else:
      self.hour = hour
    if not 0 <= minute < 60:
      raise ValueError('The minutes value must be between 0 and 59 inclusive.')
    else:
      self.minute = minute
    if not 0 <= second < 60:
      raise ValueError('The seconds value must be between 0 and 59 inclusive.')
    else:
      self.second = second
    if not 0 <= microsecond < 1000000:
      raise ValueError('The microseconds value must be between 0 and 999999 inclusive.')
    else:
      self.microsecond = microsecond

  def __repr__(self):
    """Return a string representation of the object."""
    return "datetime.time(%s, %s, %s)" % (self.hour, self.minute, self.second)

  def isoformat(self):
    """Return the time as a standard SQL string in the format 'HH:MM::SS.ss'."""
    return self._isotime()

  def timetuple(self):
    raise AttributeError('time objects do not have a timetuple method.')

  def now(self):
    """Return the current date and time as a datetime."""
    now = t.localtime()
    return time(now[3], now[4], now[5])
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.