Logo Search packages:      
Sourcecode: poco version File versions

DateTime.cpp

//
// DateTime.cpp
//
// $Id: //poco/1.3/Foundation/src/DateTime.cpp#3 $
//
// Library: Foundation
// Package: DateTime
// Module:  DateTime
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
// 
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
//


#include "Poco/DateTime.h"
#include "Poco/Timespan.h"
#include <algorithm>
#include <cmath>


namespace Poco {


00046 inline double DateTime::toJulianDay(Timestamp::UtcTimeVal utcTime)
{
      double utcDays = double(utcTime)/864000000000.0;
      return utcDays + 2299160.5; // first day of Gregorian reform (Oct 15 1582)
}


00053 inline Timestamp::UtcTimeVal DateTime::toUtcTime(double julianDay)
{
      return Timestamp::UtcTimeVal((julianDay - 2299160.5)*864000000000.0);
}


DateTime::DateTime()
{
      Timestamp now;
      _utcTime = now.utcTime();
      computeGregorian(julianDay());
      computeDaytime();
}


00068 DateTime::DateTime(const Timestamp& timestamp):
      _utcTime(timestamp.utcTime())
{
      computeGregorian(julianDay());
      computeDaytime();
}

      
00076 DateTime::DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond):
      _year(year),
      _month(month),
      _day(day),
      _hour(hour),
      _minute(minute),
      _second(second),
      _millisecond(millisecond),
      _microsecond(microsecond)
{
      poco_assert (year >= 0 && year <= 9999);
      poco_assert (month >= 1 && month <= 12);
      poco_assert (day >= 1 && day <= daysOfMonth(year, month));
      poco_assert (hour >= 0 && hour <= 23);
      poco_assert (minute >= 0 && minute <= 59);
      poco_assert (second >= 0 && second <= 59);
      poco_assert (millisecond >= 0 && millisecond <= 999);
      poco_assert (microsecond >= 0 && microsecond <= 999);
      
      _utcTime = toUtcTime(toJulianDay(year, month, day)) + 10*(hour*Timespan::HOURS + minute*Timespan::MINUTES + second*Timespan::SECONDS + millisecond*Timespan::MILLISECONDS + microsecond);
}


00099 DateTime::DateTime(double julianDay):
      _utcTime(toUtcTime(julianDay))
{
      computeGregorian(julianDay);
}


00106 DateTime::DateTime(Timestamp::UtcTimeVal utcTime, Timestamp::TimeDiff diff):
      _utcTime(utcTime + diff*10)
{
      computeGregorian(julianDay());
      computeDaytime();
}


00114 DateTime::DateTime(const DateTime& dateTime):
      _utcTime(dateTime._utcTime),
      _year(dateTime._year),
      _month(dateTime._month),
      _day(dateTime._day),
      _hour(dateTime._hour),
      _minute(dateTime._minute),
      _second(dateTime._second),
      _millisecond(dateTime._millisecond),
      _microsecond(dateTime._microsecond)
{
}


00128 DateTime::~DateTime()
{
}


00133 DateTime& DateTime::operator = (const DateTime& dateTime)
{
      if (&dateTime != this)
      {
            _utcTime     = dateTime._utcTime;
            _year        = dateTime._year;
            _month       = dateTime._month;
            _day         = dateTime._day;
            _hour        = dateTime._hour;
            _minute      = dateTime._minute;
            _second      = dateTime._second;
            _millisecond = dateTime._millisecond;
            _microsecond = dateTime._microsecond;
      }
      return *this;
}

      
00151 DateTime& DateTime::operator = (const Timestamp& timestamp)
{
      _utcTime = timestamp.utcTime();
      computeGregorian(julianDay());
      computeDaytime();
      return *this;
}


00160 DateTime& DateTime::operator = (double julianDay)
{
      _utcTime = toUtcTime(julianDay);
      computeGregorian(julianDay);
      return *this;
}


00168 DateTime& DateTime::assign(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond)
{
      poco_assert (year >= 0 && year <= 9999);
      poco_assert (month >= 1 && month <= 12);
      poco_assert (day >= 1 && day <= daysOfMonth(year, month));
      poco_assert (hour >= 0 && hour <= 23);
      poco_assert (minute >= 0 && minute <= 59);
      poco_assert (second >= 0 && second <= 59);
      poco_assert (millisecond >= 0 && millisecond <= 999);
      poco_assert (microsecond >= 0 && microsecond <= 999);

      _utcTime     = toUtcTime(toJulianDay(year, month, day)) + 10*(hour*Timespan::HOURS + minute*Timespan::MINUTES + second*Timespan::SECONDS + millisecond*Timespan::MILLISECONDS + microsecond);
      _year        = year;
      _month       = month;
      _day         = day;
      _hour        = hour;
      _minute      = minute;
      _second      = second;
      _millisecond = millisecond;
      _microsecond = microsecond;
      
      return *this;
}


00193 void DateTime::swap(DateTime& dateTime)
{
      std::swap(_utcTime, dateTime._utcTime);
      std::swap(_year, dateTime._year);
      std::swap(_month, dateTime._month);
      std::swap(_day, dateTime._day);
      std::swap(_hour, dateTime._hour);
      std::swap(_minute, dateTime._minute);
      std::swap(_second, dateTime._second);
      std::swap(_millisecond, dateTime._millisecond);
      std::swap(_microsecond, dateTime._microsecond);
}


00207 int DateTime::dayOfWeek() const
{
      return int((std::floor(julianDay() + 1.5))) % 7;
}


00213 int DateTime::dayOfYear() const
{
      int doy = 0;
      for (int month = 1; month < _month; ++month)
            doy += daysOfMonth(_year, month);
      doy += _day;
      return doy;
}


00223 int DateTime::daysOfMonth(int year, int month)
{
      poco_assert (month >= 1 && month <= 12);

      static int daysOfMonthTable[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
      
      if (month == 2 && isLeapYear(year))
            return 29;
      else
            return daysOfMonthTable[month];
}


00236 bool DateTime::isValid(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond)
{
      return
            (year >= 0 && year <= 9999) &&
            (month >= 1 && month <= 12) &&
            (day >= 1 && day <= daysOfMonth(year, month)) &&
            (hour >= 0 && hour <= 23) &&
            (minute >= 0 && minute <= 59) &&
            (second >= 0 && second <= 59) &&
            (millisecond >= 0 && millisecond <= 999) &&
            (microsecond >= 0 && microsecond <= 999);
}


00250 int DateTime::week(int firstDayOfWeek) const
{
      poco_assert (firstDayOfWeek >= 0 && firstDayOfWeek <= 6);

      /// find the first firstDayOfWeek.
      int baseDay = 1;
      while (DateTime(_year, 1, baseDay).dayOfWeek() != firstDayOfWeek) ++baseDay;

      int doy  = dayOfYear();
      int offs = baseDay <= 4 ? 0 : 1; 
      if (doy < baseDay)
            return offs;
      else
            return (doy - baseDay)/7 + 1 + offs;
}


00267 double DateTime::julianDay() const
{
      return toJulianDay(_utcTime);
}


DateTime DateTime::operator + (const Timespan& span) const
{
      return DateTime(_utcTime, span.totalMicroseconds());
}


DateTime DateTime::operator - (const Timespan& span) const
{
      return DateTime(_utcTime, -span.totalMicroseconds());
}


Timespan DateTime::operator - (const DateTime& dateTime) const
{
      return Timespan((_utcTime - dateTime._utcTime)/10);
}


DateTime& DateTime::operator += (const Timespan& span)
{
      _utcTime += span.totalMicroseconds()*10;
      computeGregorian(julianDay());
      computeDaytime();
      return *this;
}


DateTime& DateTime::operator -= (const Timespan& span)
{
      _utcTime -= span.totalMicroseconds()*10;
      computeGregorian(julianDay());
      computeDaytime();
      return *this;
}


void DateTime::makeUTC(int tzd)
{
      operator -= (Timespan(((Timestamp::TimeDiff) tzd)*Timespan::SECONDS));
}

      
00315 void DateTime::makeLocal(int tzd)
{
      operator += (Timespan(((Timestamp::TimeDiff) tzd)*Timespan::SECONDS));
}


00321 double DateTime::toJulianDay(int year, int month, int day, int hour, int minute, int second, int millisecond, int microsecond)
{
      // lookup table for (153*month - 457)/5 - note that 3 <= month <= 14.
      static int lookup[] = {-91, -60, -30, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337};
 
      // day to double
      double dday = double(day) + ((double((hour*60 + minute)*60 + second)*1000 + millisecond)*1000 + microsecond)/86400000000.0;
      if (month < 3)
      {
            month += 12;
            --year;
      }
      double dyear = double(year);
      return dday + lookup[month] + 365*year + std::floor(dyear/4) - std::floor(dyear/100) + std::floor(dyear/400) + 1721118.5;
}


00338 void DateTime::checkLimit(short& lower, short& higher, short limit)
{
      if (lower > limit)
      {
            higher += short(lower / limit);
            lower   = short(lower % limit);
      }
}


void DateTime::normalize()
{
      checkLimit(_microsecond, _millisecond, 999);
      checkLimit(_millisecond, _second, 999);
      checkLimit(_second, _minute, 59);
      checkLimit(_minute, _hour, 59);
      checkLimit(_hour, _day, 23);

      if (_day > daysOfMonth(_year, _month))
      {
            _day -= daysOfMonth(_year, _month);
            if (++_month > 12)
            {
                  ++_year;
                  _month -= 12;
            }
      }
}


00368 void DateTime::computeGregorian(double julianDay)
{
      double z    = std::floor(julianDay - 1721118.5);
      double r    = julianDay - 1721118.5 - z;
      double g    = z - 0.25;
      double a    = std::floor(g / 36524.25);
      double b    = a - std::floor(a/4);
      _year       = short(std::floor((b + g)/365.25));
      double c    = b + z - std::floor(365.25*_year);
      _month      = short(std::floor((5*c + 456)/153));
      double dday = c - std::floor((153.0*_month - 457)/5) + r;
      _day        = short(dday);
      if (_month > 12)
      {
            ++_year;
            _month -= 12;
      }
      r      *= 24;
      _hour   = short(std::floor(r));
      r      -= std::floor(r);
      r      *= 60;
      _minute = short(std::floor(r));
      r      -= std::floor(r);
      r      *= 60;
      _second = short(std::floor(r));
      r      -= std::floor(r);
      r      *= 1000;
      _millisecond = short(std::floor(r));
      r      -= std::floor(r);
      r      *= 1000;
      _microsecond = short(r + 0.5);

      normalize();

      poco_assert_dbg (_month >= 1 && _month <= 12);
      poco_assert_dbg (_day >= 1 && _day <= daysOfMonth(_year, _month));
      poco_assert_dbg (_hour >= 0 && _hour <= 23);
      poco_assert_dbg (_minute >= 0 && _minute <= 59);
      poco_assert_dbg (_second >= 0 && _second <= 59);
      poco_assert_dbg (_millisecond >= 0 && _millisecond <= 999);
      poco_assert_dbg (_microsecond >= 0 && _microsecond <= 999);
}


00412 void DateTime::computeDaytime()
{
      Timespan span(_utcTime/10);
      _hour        = span.hours();
      _minute      = span.minutes();
      _second      = span.seconds();
      _millisecond = span.milliseconds();
      _microsecond = span.microseconds();
}


} // namespace Poco

Generated by  Doxygen 1.6.0   Back to index