#include "Zeit.h"

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

#include "Text.h"
#ifdef WIN32
#    include "Fenster.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 Uhrzeit class from Zeit.h
// Private
int Uhrzeit::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;
}

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

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

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

int Uhrzeit::setUhrzeit(
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 Uhrzeit::setUhrzeit(const char* format, Text* zeit)
{
    int ret = setUhrzeit(format, zeit->getText());
    zeit->release();
    return ret;
}

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

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

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

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

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

int Uhrzeit::plusUhrzeit(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 Uhrzeit::plusUhrzeit(const char* format, Text* zeit)
{
    int ret = plusUhrzeit(format, zeit->getText());
    zeit->release();
    return ret;
}

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

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

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

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

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

int Uhrzeit::minusUhrzeit(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 Uhrzeit::minusUhrzeit(const char* format, Text* zeit)
{
    int ret = plusUhrzeit(format, zeit->getText());
    zeit->release();
    return ret;
}

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

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

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

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

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

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

Text* Uhrzeit::getUhrzeit(
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 Uhrzeit::istGleich(
Uhrzeit* zeit) const // checks if the time equals zeit
{
    bool ret = stunde == zeit->getStunde() && minute == zeit->getMinute()
            && sekunde == zeit->getSekunde();
    zeit->release();
    return ret;
}

bool Uhrzeit::istGleich(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 Uhrzeit::istGleich(const char* format, Text* zeit) const
{
    bool ret = istGleich(format, zeit->getText());
    zeit->release();
    return ret;
}

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

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

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

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

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

bool Uhrzeit::istKleiner(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 Uhrzeit::istKleiner(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 istKleiner(st, min, sek);
}

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

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

bool Uhrzeit::istLater(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 Uhrzeit::istLater(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 istLater(st, min, sek);
}

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

// Content of the Datum class from Zeit.h
// Private
void Datum::update() // calculates the new date
{
    while (monat > 12)
    {
        monat -= 12;
        ++jahr;
    }
    while (monat <= 0)
    {
        monat += 12;
        --jahr;
    }
    if (istSchaltjahr(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 (istSchaltjahr(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 (istSchaltjahr(jahr))
                maxTage[1] = 29;
            else
                maxTage[1] = 28;
        }
    }
}

// Constructor
Datum::Datum()
    : 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
Datum::~Datum()
{
    delete[] maxTage;
}

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

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

void Datum::setDatum(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 Datum::setDatum(const char* format, Text* datum)
{
    setDatum(format, datum->getText());
    datum->release();
}

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

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

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

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

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

void Datum::plusDatum(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 Datum::plusDatum(const char* format, Text* datum)
{
    plusDatum(format, datum->getText());
    datum->release();
}

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

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

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

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

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

void Datum::minusDatum(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 Datum::minusDatum(const char* format, Text* datum)
{
    minusDatum(format, datum->getText());
    datum->release();
}

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

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

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

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

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

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

Text* Datum::getDatum(
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 Datum::istGleich(
Datum* datum) const // checks if the date equals datum
{
    bool ret = jahr == datum->getJahr() && monat == datum->getMonat()
            && tag == datum->getTag();
    datum->release();
    return ret;
}

bool Datum::istGleich(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 Datum::istGleich(const char* format, Text* datum) const
{
    bool ret = istGleich(format, datum->getText());
    datum->release();
    return ret;
}

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

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

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

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

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

bool Datum::istKleiner(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 Datum::istKleiner(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 istKleiner(j, m, t);
}

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

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

bool Datum::istLater(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 Datum::istLater(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 istLater(j, m, t);
}

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

// Content of the Zeit class from Zeit.h
// Constructor
Zeit::Zeit()
    : ReferenceCounter(),
      datum(new Datum()),
      uhrzeit(new Uhrzeit())
{}

//! Creates a new Zeit with the elapsed seconds since 1970.
Zeit::Zeit(__int64 timestamp)
    : ReferenceCounter(),
      datum(new Datum()),
      uhrzeit(new Uhrzeit())
{
    datum->setDatum(1970, 1, 1);
    plusSekunde(timestamp);
}

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

// non-constant
void Zeit::setZeit(Zeit* zeit) // sets the time
{
    datum->setDatum(zeit->getDatum());
    datum->plusTag(uhrzeit->setUhrzeit(zeit->getUhrzeit()));
    zeit->release();
}

void Zeit::setZeit(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde)
{
    datum->setDatum(jahr, monat, tag);
    datum->plusTag(uhrzeit->setUhrzeit(stunde, minute, sekunde));
}

void Zeit::setZeit(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->setDatum(y, m, d);
    datum->plusTag(uhrzeit->setUhrzeit(h, i, s));
}

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

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

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

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

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

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

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

void Zeit::plusZeit(Zeit* zeit) // adds the time
{
    datum->plusDatum(zeit->getDatum());
    datum->plusTag(uhrzeit->plusUhrzeit(zeit->getUhrzeit()));
    zeit->release();
}

void Zeit::plusZeit(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde)
{
    datum->plusDatum(jahr, monat, tag);
    datum->plusTag(uhrzeit->plusUhrzeit(stunde, minute, sekunde));
}

void Zeit::plusZeit(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->setDatum(y, m, d);
    datum->plusTag(uhrzeit->setUhrzeit(h, i, s));
}

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

void Zeit::plusJahr(int jahr) // adds jahr years
{
    datum->plusJahr(jahr);
}

void Zeit::plusMonat(int monat) // adds monat months
{
    datum->plusMonat(monat);
}

void Zeit::plusTag(int tag) // adds tag days
{
    datum->plusTag(tag);
}

void Zeit::plusStunde(__int64 stunde) // adds stunde hours
{
    datum->plusTag(uhrzeit->plusStunde(stunde));
}

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

void Zeit::plusSekunde(__int64 sekunde) // adds sekunde seconds
{
    datum->plusTag(uhrzeit->plusSekunde(sekunde));
}

void Zeit::minusZeit(Zeit* zeit) // subtracts the time
{
    datum->minusDatum(zeit->getDatum());
    datum->plusTag(uhrzeit->minusUhrzeit(zeit->getUhrzeit()));
    zeit->release();
}

void Zeit::minusZeit(
    int jahr, int monat, int tag, int stunde, int minute, int sekunde)
{
    datum->minusDatum(jahr, monat, tag);
    datum->plusTag(uhrzeit->plusUhrzeit(stunde, minute, sekunde));
}

void Zeit::minusZeit(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->setDatum(y, m, d);
    datum->plusTag(uhrzeit->setUhrzeit(h, i, s));
}

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

void Zeit::minusJahr(int jahr) // subtracts jahr years
{
    datum->minusJahr(jahr);
}

void Zeit::minusMonat(int monat) // subtracts monat months
{
    datum->minusMonat(monat);
}

void Zeit::minusTag(int tag) // subtracts tag days
{
    datum->minusTag(tag);
}

void Zeit::minusStunde(__int64 stunde) // subtracts stunde hours
{
    datum->plusTag(uhrzeit->minusStunde(stunde));
}

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

void Zeit::minusSekunde(__int64 sekunde) // subtracts sekunde seconds
{
    datum->plusTag(uhrzeit->minusSekunde(sekunde));
}

// constant
Text* Zeit::getZeit(
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 Zeit::istGleich(Zeit* zeit) const // checks if the time equals zeit
{
    bool ret = datum->istGleich(zeit->getDatum())
            && uhrzeit->istGleich(zeit->getUhrzeit());
    zeit->release();
    return ret;
}

bool Zeit::istGleich(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->istGleich(y, m, d) && uhrzeit->istGleich(h, i, s);
}

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

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

Datum* Zeit::getDatum() const // returns the date
{
    return dynamic_cast<Datum*>(datum->getThis());
}

Datum* Zeit::zDatum() const
{
    return datum;
}

Uhrzeit* Zeit::getUhrzeit() const // returns the time of day
{
    return dynamic_cast<Uhrzeit*>(uhrzeit->getThis());
}

Uhrzeit* Zeit::zUhrzeit() const
{
    return uhrzeit;
}

bool Zeit::istKleiner(
Zeit* zeit) const // checks if the time is less than zeit
{
    if (datum->istKleiner(zeit->getDatum()))
    {
        zeit->release();
        return 1;
    }
    else if (datum->istGleich(zeit->getDatum()))
    {
        if (uhrzeit->istKleiner(zeit->getUhrzeit()))
        {
            zeit->release();
            return 1;
        }
        else
        {
            zeit->release();
            return 0;
        }
    }
    else
    {
        zeit->release();
        return 0;
    }
}

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

bool Zeit::istKleiner(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->istKleiner(y, m, d))
        return 1;
    else if (datum->istGleich(y, m, d))
    {
        if (uhrzeit->istKleiner(h, i, s))
            return 1;
        else
            return 0;
    }
    else
        return 0;
}

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

bool Zeit::istLater(
Zeit* zeit) const // checks if the time is greater than zeit
{
    if (datum->istLater(zeit->getDatum()))
    {
        zeit->release();
        return 1;
    }
    else if (datum->istGleich(zeit->getDatum()))
    {
        if (uhrzeit->istLater(zeit->getUhrzeit()))
        {
            zeit->release();
            return 1;
        }
        else
        {
            zeit->release();
            return 0;
        }
    }
    else
    {
        zeit->release();
        return 0;
    }
}

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

bool Zeit::istLater(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->istLater(y, m, d))
        return 1;
    else if (datum->istGleich(y, m, d))
    {
        if (uhrzeit->istLater(h, i, s))
            return 1;
        else
            return 0;
    }
    else
        return 0;
}

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

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

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

// non-constant
void ZeitMesser::messungStart() // 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 ZeitMesser::messungEnde() // 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 ZeitMesser::getSekunden() const // returns the second difference between
// start and end of the measurement
{
    return messung;
}

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

double ZeitMesser::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 ZeitMesser::isMeasuring() const
{
    return start != 0;
}

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

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

Zeit* Framework::getZeit() // returns the current time (date and time of day)
{
#ifdef WIN32
    Zeit* ret = new Zeit();
    time_t Zeitstempel = time(0);
    tm now;
    localtime_s(&now, &Zeitstempel);
    ret->setZeit(now.tm_year + 1900,
        now.tm_mon + 1,
        now.tm_mday,
        now.tm_hour,
        now.tm_min,
        now.tm_sec);
    return ret;
#else
    Zeit* ret = new Zeit();
    time_t Zeitstempel = time(0);
    tm* now = localtime(&Zeitstempel);
    ret->setZeit(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::istSchaltjahr(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;
}