#include "Timer.h"

#include <ctime>
#include <time.h>

#include "Text.h"
#ifdef WIN32
#    include "Window.h"
#else
#    include <string.h>
#    include <sys/time.h>
#endif

#ifdef WIN32

#    if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#        define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#    else
#        define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#    endif

struct timeval
{
    long tv_sec;  // seconds since 1/1/1970
    long tv_usec; // and microseconds
};

struct timezone
{
    int tz_minuteswest; // minutes W of Greenwich
    int tz_dsttime;     // type of dst correction
};

int gettimeofday(struct timeval* tv, struct timezone* tz)
{
    FILETIME ft;
    unsigned __int64 tmpres = 0;
    static int tzflag;

    if (NULL != tv)
    {
        GetSystemTimeAsFileTime(&ft);

        tmpres |= ft.dwHighDateTime;
        tmpres <<= 32;
        tmpres |= ft.dwLowDateTime;

        // converting file time to unix epoch
        tmpres -= DELTA_EPOCH_IN_MICROSECS;
        tmpres /= 10; // convert into microseconds
        tv->tv_sec = (long)(tmpres / 1000000UL);
        tv->tv_usec = (long)(tmpres % 1000000UL);
    }

    if (NULL != tz)
    {
        if (!tzflag)
        {
            _tzset();
            ++tzflag;
        }
        _get_timezone((long*)&(tz->tz_minuteswest));
        tz->tz_minuteswest /= 60;
        _get_daylight(&(tz->tz_dsttime));
    }

    return 0;
}

#endif

using namespace Framework;

// Content of the Clock class from Time.h
// Private
int Clock::update() // calculates the new time
{
    __int64 mins = sekunde / 60;
    minute = minute + mins;
    __int64 hours = (minute) / 60;
    stunde = stunde + hours;
    int days = (int)((stunde) / 24);
    sekunde = sekunde - (mins * 60);
    minute = minute - (hours * 60);
    stunde = stunde - (days * 24);
    while (sekunde < 0)
    {
        sekunde += 60;
        --minute;
    }
    while (minute < 0)
    {
        minute += 60;
        --stunde;
    }
    while (stunde < 0)
    {
        stunde += 24;
        --days;
    }
    return days;
}

Clock::Clock()
    : ReferenceCounter(),
      stunde(0),
      minute(0),
      sekunde(0)
{}

int Clock::setClock(Clock* zeit) // sets the time
{
    stunde = zeit->getStunde();
    minute = zeit->getMinute();
    sekunde = zeit->getSekunde();
    zeit->release();
    return update();
}

int Clock::setClock(int stunde, int minute, int sekunde)
{
    this->stunde = stunde;
    this->minute = minute;
    this->sekunde = sekunde;
    return update();
}

int Clock::setClock(
    const char* format, const char* zeit) // format examples: "H:i:s", "H-i-s"
                                          // (H=hour,i=minute,s=second)
{
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'h':
            stunde = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            minute = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            sekunde = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    return update();
}

int Clock::setClock(const char* format, Text* zeit)
{
    int ret = setClock(format, zeit->getText());
    zeit->release();
    return ret;
}

int Clock::setStunde(int stunde) // sets the hour
{
    this->stunde = stunde;
    return update();
}

int Clock::setMinute(int minute) // sets the minute
{
    this->minute = minute;
    return update();
}

int Clock::setSekunde(int sekunde) // sets the second
{
    this->sekunde = sekunde;
    return update();
}

int Clock::plusClock(Clock* zeit) // adds the times
{
    stunde += zeit->getStunde();
    minute += zeit->getMinute();
    sekunde += zeit->getSekunde();
    return update();
}

int Clock::plusClock(int stunde, int minute, int sekunde)
{
    this->stunde += stunde;
    this->minute += minute;
    this->sekunde += sekunde;
    return update();
}

int Clock::plusClock(const char* format, const char* zeit)
{
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'h':
            stunde += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            minute += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            sekunde += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    return update();
}

int Clock::plusClock(const char* format, Text* zeit)
{
    int ret = plusClock(format, zeit->getText());
    zeit->release();
    return ret;
}

int Clock::plusHour(__int64 stunde) // adds stunde hours
{
    this->stunde += stunde;
    return update();
}

int Clock::plusMinute(__int64 minute) // adds minute minutes
{
    this->minute += minute;
    return update();
}

int Clock::plusSecond(__int64 sekunde) // adds sekunde seconds
{
    this->sekunde += sekunde;
    return update();
}

int Clock::minusClock(Clock* zeit) // subtracts the times
{
    stunde -= zeit->getStunde();
    minute -= zeit->getMinute();
    sekunde -= zeit->getSekunde();
    zeit->release();
    return update();
}

int Clock::minusClock(int stunde, int minute, int sekunde)
{
    this->stunde -= stunde;
    this->minute -= minute;
    this->sekunde -= sekunde;
    return update();
}

int Clock::minusClock(const char* format, const char* zeit)
{
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'h':
            stunde -= TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            minute -= TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            sekunde -= TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    return update();
}

int Clock::minusClock(const char* format, Text* zeit)
{
    int ret = plusClock(format, zeit->getText());
    zeit->release();
    return ret;
}

int Clock::minusHour(__int64 stunde) // subtracts stunde hours
{
    this->stunde -= stunde;
    return update();
}

int Clock::minusMinute(__int64 minute) // subtracts minute minutes
{
    this->minute -= minute;
    return update();
}

int Clock::minusSecond(__int64 sekunde) // subtracts sekunde seconds
{
    this->sekunde -= sekunde;
    return update();
}

// constant
int Clock::getStunde() const // returns the hour
{
    return (int)stunde;
}

int Clock::getMinute() const // returns the minute
{
    return (int)minute;
}

int Clock::getSekunde() const // returns the second
{
    return (int)sekunde;
}

Text* Clock::getClock(
    const char* format) const // returns the time formatted as text
{
    Text* ret = new Text("");
    int flen = textLength(format);
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'h':
            ret->append(stunde);
            break;
        case 'i':
            ret->append(minute);
            break;
        case 's':
            ret->append(sekunde);
            break;
        default:
            ret->append(f, 1);
            break;
        }
    }
    return ret;
}

bool Clock::isEqual(Clock* zeit) const // checks if the time equals zeit
{
    bool ret = stunde == zeit->getStunde() && minute == zeit->getMinute()
            && sekunde == zeit->getSekunde();
    zeit->release();
    return ret;
}

bool Clock::isEqual(const char* format, const char* zeit) const
{
    int st = (int)stunde, min = (int)minute, sek = (int)sekunde;
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'h':
            st = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            min = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            sek = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    bool ret = stunde == st && minute == min && sekunde == sek;
    return ret;
}

bool Clock::isEqual(const char* format, Text* zeit) const
{
    bool ret = isEqual(format, zeit->getText());
    zeit->release();
    return ret;
}

bool Clock::isEqual(int stunde, int minute, int sekunde) const
{
    return this->stunde == stunde && this->minute == minute
        && this->sekunde == sekunde;
}

bool Clock::hourEqual(int stunde) const // checks if the hour equals stunde
{
    return this->stunde == stunde;
}

bool Clock::minuteEqual(int minute) const // checks if the minute equals minute
{
    return this->minute == minute;
}

bool Clock::secondEqual(
    int sekunde) const // checks if the second equals sekunde
{
    return this->sekunde == sekunde;
}

bool Clock::isSmaller(Clock* zeit) const // checks if the time is less than zeit
{
    bool ret
        = isSmaller(zeit->getStunde(), zeit->getMinute(), zeit->getSekunde());
    zeit->release();
    return ret;
}

bool Clock::isSmaller(int stunde, int minute, int sekunde) const
{
    if (this->stunde < stunde)
        return 1;
    else if (this->stunde == stunde)
    {
        if (this->minute < minute)
            return 1;
        else if (this->minute == minute)
        {
            if (this->sekunde < sekunde)
                return 1;
            else if (this->sekunde == sekunde)
                return 0;
            else
                return 0;
        }
        else
            return 0;
    }
    else
        return 0;
}

bool Clock::isSmaller(const char* format, const char* zeit) const
{
    int st = (int)stunde, min = (int)minute, sek = (int)sekunde;
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'h':
            st = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            min = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            sek = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    return isSmaller(st, min, sek);
}

bool Clock::isSmaller(const char* format, Text* zeit) const
{
    bool ret = isSmaller(format, zeit->getText());
    zeit->release();
    return ret;
}

bool Clock::isLater(
    Clock* zeit) const // checks if the time is greater than zeit
{
    bool ret
        = isLater(zeit->getStunde(), zeit->getMinute(), zeit->getSekunde());
    zeit->release();
    return ret;
}

bool Clock::isLater(int stunde, int minute, int sekunde) const
{
    if (this->stunde > stunde)
        return 1;
    else if (this->stunde == stunde)
    {
        if (this->minute > minute)
            return 1;
        else if (this->minute == minute)
        {
            if (this->sekunde > sekunde)
                return 1;
            else if (this->sekunde == sekunde)
                return 0;
            else
                return 0;
        }
        else
            return 0;
    }
    else
        return 0;
}

bool Clock::isLater(const char* format, const char* zeit) const
{
    int st = (int)stunde, min = (int)minute, sek = (int)sekunde;
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'h':
            st = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            min = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            sek = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    return isLater(st, min, sek);
}

bool Clock::isLater(const char* format, Text* zeit) const
{
    bool ret = isLater(format, zeit->getText());
    zeit->release();
    return ret;
}

// Content of the Date class from Time.h
// Private
void Date::update() // calculates the new date
{
    while (monat > 12)
    {
        monat -= 12;
        ++jahr;
    }
    while (monat <= 0)
    {
        monat += 12;
        --jahr;
    }
    if (isLeapYear(jahr))
        maxTage[1] = 29;
    else
        maxTage[1] = 28;
    while (tag > maxTage[monat - 1])
    {
        tag -= maxTage[monat - 1];
        ++monat;
        if (monat > 12)
        {
            monat -= 12;
            ++jahr;
            if (isLeapYear(jahr))
                maxTage[1] = 29;
            else
                maxTage[1] = 28;
        }
    }
    while (tag <= 0)
    {
        tag += maxTage[(monat - 2 > 0 ? monat - 2 : 11)];
        --monat;
        if (monat <= 0)
        {
            monat += 12;
            --jahr;
            if (isLeapYear(jahr))
                maxTage[1] = 29;
            else
                maxTage[1] = 28;
        }
    }
}

// Constructor
Date::Date()
    : ReferenceCounter(),
      jahr(0),
      monat(0),
      tag(0)
{
    int maxT[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    maxTage = new int[12];
    memcpy(maxTage, maxT, 12 * sizeof(int));
}

// Destructor
Date::~Date()
{
    delete[] maxTage;
}

// non-constant
void Date::setDate(Date* datum) // sets the date
{
    jahr = datum->getJahr();
    monat = datum->getMonat();
    tag = datum->getTag();
    datum->release();
    update();
}

void Date::setDate(int jahr, int monat, int tag)
{
    this->jahr = jahr;
    this->monat = monat;
    this->tag = tag;
    update();
}

void Date::setDate(const char* format,
    const char*
        datum) // format examples: "Y:m:d", "Y-m-d" (Y=year,m=month,d=day)
{
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            jahr = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'm':
            monat = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'd':
            tag = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        default:
            ++datum;
            break;
        }
    }
    update();
}

void Date::setDate(const char* format, Text* datum)
{
    setDate(format, datum->getText());
    datum->release();
}

void Date::setJahr(int jahr) // sets the year
{
    this->jahr = jahr;
    update();
}

void Date::setMonat(int monat) // sets the month
{
    this->monat = monat;
    update();
}

void Date::setTag(int tag) // sets the day
{
    this->tag = tag;
    update();
}

void Date::plusDate(Date* datum) // adds the date
{
    this->jahr += datum->getJahr();
    this->monat += datum->getMonat();
    this->tag += datum->getTag();
    datum->release();
    update();
}

void Date::plusDate(int jahr, int monat, int tag)
{
    this->jahr += jahr;
    this->monat += monat;
    this->tag += tag;
    update();
}

void Date::plusDate(const char* format, const char* datum)
{
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            jahr += TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'm':
            monat += TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'd':
            tag += TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        default:
            ++datum;
            break;
        }
    }
    update();
}

void Date::plusDate(const char* format, Text* datum)
{
    plusDate(format, datum->getText());
    datum->release();
}

void Date::plusYear(int jahr) // adds jahr years
{
    this->jahr += jahr;
    update();
}

void Date::plusMonth(int monat) // adds monat months
{
    this->monat = monat;
    update();
}

void Date::plusDay(int tag) // adds tag days
{
    this->tag += tag;
    update();
}

void Date::minusDate(Date* datum) // subtracts the date
{
    jahr -= datum->getJahr();
    monat -= datum->getMonat();
    tag -= datum->getTag();
    datum->release();
    update();
}

void Date::minusDate(int jahr, int monat, int tag)
{
    this->jahr -= jahr;
    this->monat -= monat;
    this->tag -= tag;
    update();
}

void Date::minusDate(const char* format, const char* datum)
{
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            jahr -= TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'm':
            monat -= TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'd':
            tag -= TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        default:
            ++datum;
            break;
        }
    }
    update();
}

void Date::minusDate(const char* format, Text* datum)
{
    minusDate(format, datum->getText());
    datum->release();
}

void Date::minusYear(int jahr) // subtracts jahr years
{
    this->jahr -= jahr;
    update();
}

void Date::minusMonth(int monat) // subtracts monat months
{
    this->monat -= monat;
    update();
}

void Date::minusDay(int tag) // subtracts tag days
{
    this->tag -= tag;
    update();
}

// constant
int Date::getJahr() const // returns the year
{
    return jahr;
}

int Date::getMonat() const // returns the month
{
    return monat;
}

int Date::getTag() const // returns the day
{
    return tag;
}

Text* Date::getDate(
    const char* format) const // returns the date formatted as text
{
    Text* ret = new Text("");
    int flen = textLength(format);
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            ret->append(jahr);
            break;
        case 'm':
            ret->append(monat);
            break;
        case 'd':
            ret->append(tag);
            break;
        default:
            ret->append(f, 1);
            break;
        }
    }
    return ret;
}

bool Date::isEqual(Date* datum) const // checks if the date equals datum
{
    bool ret = jahr == datum->getJahr() && monat == datum->getMonat()
            && tag == datum->getTag();
    datum->release();
    return ret;
}

bool Date::isEqual(const char* format, const char* datum) const
{
    int j = jahr, m = monat, t = tag;
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            j = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'm':
            m = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'd':
            t = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        default:
            ++datum;
            break;
        }
    }
    bool ret = jahr == j && monat == m && tag == t;
    return ret;
}

bool Date::isEqual(const char* format, Text* datum) const
{
    bool ret = isEqual(format, datum->getText());
    datum->release();
    return ret;
}

bool Date::isEqual(int jahr, int monat, int tag) const
{
    return this->jahr == jahr && this->monat == monat && this->tag == tag;
}

bool Date::yearEqual(int jahr) const // checks if the year equals jahr
{
    return this->jahr == jahr;
}

bool Date::monthEqual(int monat) const // checks if the month equals monat
{
    return this->monat == monat;
}

bool Date::dayEqual(int tag) const // checks if the day equals tag
{
    return this->tag == tag;
}

bool Date::isSmaller(Date* datum) const // checks if the date is less than datum
{
    bool ret = isSmaller(datum->getJahr(), datum->getMonat(), datum->getTag());
    datum->release();
    return ret;
}

bool Date::isSmaller(int jahr, int monat, int tag) const
{
    if (this->jahr < jahr)
        return 1;
    else if (this->jahr == jahr)
    {
        if (this->monat < monat)
            return 1;
        else if (this->monat == monat)
        {
            if (this->tag < tag)
                return 1;
            else if (this->tag == tag)
                return 0;
            else
                return 0;
        }
        else
            return 0;
    }
    else
        return 0;
}

bool Date::isSmaller(const char* format, const char* datum) const
{
    int j = jahr, m = monat, t = tag;
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            j = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'm':
            m = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'd':
            t = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        default:
            ++datum;
            break;
        }
    }
    return isSmaller(j, m, t);
}

bool Date::isSmaller(const char* format, Text* datum) const
{
    bool ret = isSmaller(format, datum->getText());
    datum->release();
    return ret;
}

bool Date::isLater(
    Date* datum) const // checks if the date is greater than datum
{
    bool ret = isLater(datum->getJahr(), datum->getMonat(), datum->getTag());
    datum->release();
    return ret;
}

bool Date::isLater(int jahr, int monat, int tag) const
{
    if (this->jahr > jahr)
        return 1;
    else if (this->jahr == jahr)
    {
        if (this->monat > monat)
            return 1;
        else if (this->monat == monat)
        {
            if (this->tag > tag)
                return 1;
            else if (this->tag == tag)
                return 0;
            else
                return 0;
        }
        else
            return 0;
    }
    else
        return 0;
}

bool Date::isLater(const char* format, const char* datum) const
{
    int j = jahr, m = monat, t = tag;
    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            j = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'm':
            m = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        case 'd':
            t = TextZuInt(datum, &ende, 10);
            datum = ende;
            ende = 0;
            break;
        default:
            ++datum;
            break;
        }
    }
    return isLater(j, m, t);
}

bool Date::isLater(const char* format, Text* datum) const
{
    bool ret = isLater(format, datum->getText());
    datum->release();
    return ret;
}

// Content of the Time class from Time.h
// Constructor
Time::Time()
    : ReferenceCounter(),
      datum(new Date()),
      uhrzeit(new Clock())
{}

//! Creates a new Time with the elapsed seconds since 1970.
Time::Time(__int64 timestamp)
    : ReferenceCounter(),
      datum(new Date()),
      uhrzeit(new Clock())
{
    datum->setDate(1970, 1, 1);
    plusSecond(timestamp);
}

// Destructor
Time::~Time()
{
    datum->release();
    uhrzeit->release();
}

// non-constant
void Time::setTime(Time* zeit) // sets the time
{
    datum->setDate(zeit->getDate());
    datum->plusDay(uhrzeit->setClock(zeit->getClock()));
    zeit->release();
}

void Time::setTime(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde)
{
    datum->setDate(jahr, monat, tag);
    datum->plusDay(uhrzeit->setClock(stunde, minute, sekunde));
}

void Time::setTime(const char* format,
    const char* zeit) // format examples: "Y:m:d H-i-s", "Y-m-d H:i:s"
                      // (Y=year,m=month,d=day,H=hour,i=minute,s=second)
{
    int y = datum->getJahr();
    int m = datum->getMonat();
    int d = datum->getTag();
    int h = uhrzeit->getStunde();
    int i = uhrzeit->getMinute();
    int s = uhrzeit->getSekunde();

    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            y = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'm':
            m = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'd':
            d = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'h':
            h = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            i = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            s = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    datum->setDate(y, m, d);
    datum->plusDay(uhrzeit->setClock(h, i, s));
}

void Time::setTime(const char* format, Text* zeit)
{
    setTime(format, zeit->getText());
    zeit->release();
}

void Time::setJahr(int jahr) // sets the year
{
    datum->setJahr(jahr);
}

void Time::setMonat(int monat) // sets the month
{
    datum->setMonat(monat);
}

void Time::setTag(int tag) // sets the day
{
    datum->setTag(tag);
}

void Time::setStunde(int stunde) // sets the hour
{
    datum->plusDay(uhrzeit->setStunde(stunde));
}

void Time::setMinute(int minute) // sets the minute
{
    datum->plusDay(uhrzeit->setMinute(minute));
}

void Time::setSekunde(int sekunde) // sets the second
{
    datum->plusDay(uhrzeit->setSekunde(sekunde));
}

void Time::plusTime(Time* zeit) // adds the time
{
    datum->plusDate(zeit->getDate());
    datum->plusDay(uhrzeit->plusClock(zeit->getClock()));
    zeit->release();
}

void Time::plusTime(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde)
{
    datum->plusDate(jahr, monat, tag);
    datum->plusDay(uhrzeit->plusClock(stunde, minute, sekunde));
}

void Time::plusTime(const char* format, const char* zeit)
{
    int y = datum->getJahr();
    int m = datum->getMonat();
    int d = datum->getTag();
    int h = uhrzeit->getStunde();
    int i = uhrzeit->getMinute();
    int s = uhrzeit->getSekunde();

    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            y += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'm':
            m += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'd':
            d += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'h':
            h += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            i += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            s += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    datum->setDate(y, m, d);
    datum->plusDay(uhrzeit->setClock(h, i, s));
}

void Time::plusTime(const char* format, Text* zeit)
{
    plusTime(format, zeit->getText());
    zeit->release();
}

void Time::plusYear(int jahr) // adds jahr years
{
    datum->plusYear(jahr);
}

void Time::plusMonth(int monat) // adds monat months
{
    datum->plusMonth(monat);
}

void Time::plusDay(int tag) // adds tag days
{
    datum->plusDay(tag);
}

void Time::plusHour(__int64 stunde) // adds stunde hours
{
    datum->plusDay(uhrzeit->plusHour(stunde));
}

void Time::plusMinute(__int64 minute) // adds minute minutes
{
    datum->plusDay(uhrzeit->plusMinute(minute));
}

void Time::plusSecond(__int64 sekunde) // adds sekunde seconds
{
    datum->plusDay(uhrzeit->plusSecond(sekunde));
}

void Time::minusTime(Time* zeit) // subtracts the time
{
    datum->minusDate(zeit->getDate());
    datum->plusDay(uhrzeit->minusClock(zeit->getClock()));
    zeit->release();
}

void Time::minusTime(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde)
{
    datum->minusDate(jahr, monat, tag);
    datum->plusDay(uhrzeit->plusClock(stunde, minute, sekunde));
}

void Time::minusTime(const char* format, const char* zeit)
{
    int y = datum->getJahr();
    int m = datum->getMonat();
    int d = datum->getTag();
    int h = uhrzeit->getStunde();
    int i = uhrzeit->getMinute();
    int s = uhrzeit->getSekunde();

    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            y -= TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'm':
            m -= TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'd':
            d -= TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'h':
            h += TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            i -= TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            s -= TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    datum->setDate(y, m, d);
    datum->plusDay(uhrzeit->setClock(h, i, s));
}

void Time::minusTime(const char* format, Text* zeit)
{
    minusTime(format, zeit->getText());
    zeit->release();
}

void Time::minusYear(int jahr) // subtracts jahr years
{
    datum->minusYear(jahr);
}

void Time::minusMonth(int monat) // subtracts monat months
{
    datum->minusMonth(monat);
}

void Time::minusDay(int tag) // subtracts tag days
{
    datum->minusDay(tag);
}

void Time::minusHour(__int64 stunde) // subtracts stunde hours
{
    datum->plusDay(uhrzeit->minusHour(stunde));
}

void Time::minusMinute(__int64 minute) // subtracts minute minutes
{
    datum->plusDay(uhrzeit->minusMinute(minute));
}

void Time::minusSecond(__int64 sekunde) // subtracts sekunde seconds
{
    datum->plusDay(uhrzeit->minusSecond(sekunde));
}

// constant
Text* Time::getTime(
    const char* format) const // returns the time formatted as text
{
    Text* ret = new Text("");
    int flen = textLength(format);
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            ret->append(datum->getJahr());
            break;
        case 'm':
            if (datum->getMonat() < 10) ret->append("0");
            ret->append(datum->getMonat());
            break;
        case 'd':
            if (datum->getTag() < 10) ret->append("0");
            ret->append(datum->getTag());
            break;
        case 'h':
            if (uhrzeit->getStunde() < 10) ret->append("0");
            ret->append(uhrzeit->getStunde());
            break;
        case 'i':
            if (uhrzeit->getMinute() < 10) ret->append("0");
            ret->append(uhrzeit->getMinute());
            break;
        case 's':
            if (uhrzeit->getSekunde() < 10) ret->append("0");
            ret->append(uhrzeit->getSekunde());
            break;
        default:
            ret->append(f, 1);
        }
    }
    return ret;
}

bool Time::isEqual(Time* zeit) const // checks if the time equals zeit
{
    bool ret
        = datum->isEqual(zeit->getDate()) && uhrzeit->isEqual(zeit->getClock());
    zeit->release();
    return ret;
}

bool Time::isEqual(const char* format, const char* zeit) const
{
    int y = datum->getJahr();
    int m = datum->getMonat();
    int d = datum->getTag();
    int h = uhrzeit->getStunde();
    int i = uhrzeit->getMinute();
    int s = uhrzeit->getSekunde();

    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            y = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'm':
            m = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'd':
            d = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'h':
            h = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            i = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            s = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    return datum->isEqual(y, m, d) && uhrzeit->isEqual(h, i, s);
}

bool Time::isEqual(const char* format, Text* zeit) const
{
    bool ret = isEqual(format, zeit->getText());
    zeit->release();
    return ret;
}

bool Time::isEqual(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde) const
{
    return datum->isEqual(jahr, monat, tag)
        && uhrzeit->isEqual(stunde, minute, sekunde);
}

Date* Time::getDate() const // returns the date
{
    return dynamic_cast<Date*>(datum->getThis());
}

Date* Time::zDate() const
{
    return datum;
}

Clock* Time::getClock() const // returns the time of day
{
    return dynamic_cast<Clock*>(uhrzeit->getThis());
}

Clock* Time::zClock() const
{
    return uhrzeit;
}

bool Time::isSmaller(Time* zeit) const // checks if the time is less than zeit
{
    if (datum->isSmaller(zeit->getDate()))
    {
        zeit->release();
        return 1;
    }
    else if (datum->isEqual(zeit->getDate()))
    {
        if (uhrzeit->isSmaller(zeit->getClock()))
        {
            zeit->release();
            return 1;
        }
        else
        {
            zeit->release();
            return 0;
        }
    }
    else
    {
        zeit->release();
        return 0;
    }
}

bool Time::isSmaller(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde) const
{
    if (datum->isSmaller(jahr, monat, tag))
        return 1;
    else if (datum->isEqual(jahr, monat, tag))
    {
        if (uhrzeit->isSmaller(stunde, minute, sekunde))
            return 1;
        else
            return 0;
    }
    else
        return 0;
}

bool Time::isSmaller(const char* format, const char* zeit) const
{
    int y = datum->getJahr();
    int m = datum->getMonat();
    int d = datum->getTag();
    int h = uhrzeit->getStunde();
    int i = uhrzeit->getMinute();
    int s = uhrzeit->getSekunde();

    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            y = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'm':
            m = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'd':
            d = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'h':
            h = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            i = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            s = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    if (datum->isSmaller(y, m, d))
        return 1;
    else if (datum->isEqual(y, m, d))
    {
        if (uhrzeit->isSmaller(h, i, s))
            return 1;
        else
            return 0;
    }
    else
        return 0;
}

bool Time::isSmaller(const char* format, Text* zeit) const
{
    bool ret = isSmaller(format, zeit->getText());
    zeit->release();
    return ret;
}

bool Time::isLater(Time* zeit) const // checks if the time is greater than zeit
{
    if (datum->isLater(zeit->getDate()))
    {
        zeit->release();
        return 1;
    }
    else if (datum->isEqual(zeit->getDate()))
    {
        if (uhrzeit->isLater(zeit->getClock()))
        {
            zeit->release();
            return 1;
        }
        else
        {
            zeit->release();
            return 0;
        }
    }
    else
    {
        zeit->release();
        return 0;
    }
}

bool Time::isLater(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde) const
{
    if (datum->isLater(jahr, monat, tag))
        return 1;
    else if (datum->isEqual(jahr, monat, tag))
    {
        if (uhrzeit->isLater(stunde, minute, sekunde))
            return 1;
        else
            return 0;
    }
    else
        return 0;
}

bool Time::isLater(const char* format, const char* zeit) const
{
    int y = datum->getJahr();
    int m = datum->getMonat();
    int d = datum->getTag();
    int h = uhrzeit->getStunde();
    int i = uhrzeit->getMinute();
    int s = uhrzeit->getSekunde();

    int flen = textLength(format);
    char* ende = 0;
    for (const char* f = format; f < format + flen; ++f)
    {
        switch (*f)
        {
        case 'y':
            y = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'm':
            m = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'd':
            d = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'h':
            h = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 'i':
            i = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        case 's':
            s = TextZuInt(zeit, &ende, 10);
            zeit = ende;
            ende = 0;
            break;
        default:
            ++zeit;
            break;
        }
    }
    if (datum->isLater(y, m, d))
        return 1;
    else if (datum->isEqual(y, m, d))
    {
        if (uhrzeit->isLater(h, i, s))
            return 1;
        else
            return 0;
    }
    else
        return 0;
}

bool Time::isLater(const char* format, Text* zeit) const
{
    bool ret = isLater(format, zeit->getText());
    zeit->release();
    return ret;
}

// Content of the Timer class from Time.h
// Constructor
Timer::Timer()
    : ReferenceCounter(),
      start(0),
      ende(0),
      messung(0)
{}

// Destructor
Timer::~Timer() {}

// non-constant
void Timer::measureStart() // sets the start point of the time measurement
{
    timeval tv;
    gettimeofday(&tv, 0);
    start = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
}

void Timer::measureEnd() // sets the end point of the time measurement
{
    timeval tv;
    gettimeofday(&tv, 0);
    ende = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
    messung = ende - start;
}

// constant
double Timer::getSekunden() const // returns the second difference between
// start and end of the measurement
{
    return messung;
}

double Timer::getMinuten() const // returns the minute difference between start
                                 // and end of the measurement
{
    return messung / 60;
}

double Timer::getStunden() const // returns the hour difference between start
                                 // and end of the measurement
{
    return messung / 3600;
}

//! returns true if a measurement is currently running
DLLEXPORT bool Timer::isMeasuring() const
{
    return start != 0;
}

// Global functions
Clock* Framework::getClock() // returns the current time of day
{
#ifdef WIN32
    Clock* ret = new Clock();
    time_t Timestamp = time(0);
    tm now;
    localtime_s(&now, &Timestamp);
    ret->setClock(now.tm_hour, now.tm_min, now.tm_sec);
    return ret;
#else
    Clock* ret = new Clock();
    time_t Timestamp = time(0);
    tm* now = localtime(&Timestamp);
    ret->setClock(now->tm_hour, now->tm_min, now->tm_sec);
    return ret;
#endif
}

Date* Framework::getDate() // returns the current date
{
#ifdef WIN32
    Date* ret = new Date();
    time_t Timestamp = time(0);
    tm now;
    localtime_s(&now, &Timestamp);
    ret->setDate(now.tm_year + 1900, now.tm_mon + 1, now.tm_mday);
    return ret;
#else
    Date* ret = new Date();
    time_t Timestamp = time(0);
    tm* now = localtime(&Timestamp);
    ret->setDate(now->tm_year + 1900, now->tm_mon + 1, now->tm_mday);
    return ret;
#endif
}

Time* Framework::getTime() // returns the current time (date and time of day)
{
#ifdef WIN32
    Time* ret = new Time();
    time_t Timestamp = time(0);
    tm now;
    localtime_s(&now, &Timestamp);
    ret->setTime(now.tm_year + 1900,
        now.tm_mon + 1,
        now.tm_mday,
        now.tm_hour,
        now.tm_min,
        now.tm_sec);
    return ret;
#else
    Time* ret = new Time();
    time_t Timestamp = time(0);
    tm* now = localtime(&Timestamp);
    ret->setTime(now->tm_year + 1900,
        now->tm_mon + 1,
        now->tm_mday,
        now->tm_hour,
        now->tm_min,
        now->tm_sec);
    return ret;
#endif
}

bool Framework::isLeapYear(int jahr) // checks if jahr is a leap year
{
    if (jahr % 4 == 0)
    {
        if (jahr % 100 == 0)
        {
            if (jahr % 400 == 0)
                return true;
            else
                return false;
        }
        else
            return true;
    }
    else
        return false;
}