#ifndef INCLUDED_BOBCAT_DATETIME_
#define INCLUDED_BOBCAT_DATETIME_

#include <ctime>
#include <iosfwd>

#include <bobcat/errno>

namespace FBB
{

class DateTime
{
    typedef struct tm TimeStruct;

    friend  std::ostream &operator<<(std::ostream &str, 
                                          DateTime const &dt);
    friend  std::istream &operator>>(std::istream &str, DateTime &dt);

    friend bool operator==(DateTime const &left, DateTime const &right);
    friend bool operator!=(DateTime const &left, DateTime const &right);
    friend bool operator<(DateTime const &left, DateTime const &right);
    friend bool operator<=(DateTime const &left, DateTime const &right);
    friend bool operator>(DateTime const &left, DateTime const &right);
    friend bool operator>=(DateTime const &left, DateTime const &right);

    public:
        enum TimeType
        {
            LOCALTIME,
            UTC
        };
        enum Month
        {
            JANUARY,
            FEBRUARY,
            MARCH,
            APRIL,
            MAY,
            JUNE,
            JULY,
            AUGUST,
            SEPTEMBER,
            OCTOBER,
            NOVEMBER,
            DECEMBER,
        };
        enum Relative
        {
            THIS_YEAR,
            LAST,
            NEXT,
            THIS_WEEK,
        };
        enum Weekday
        {
            SUNDAY,
            MONDAY,
            TUESDAY,
            WEDNESDAY,
            THURSDAY,
            FRIDAY,
            SATURDAY,
        };
        enum TriVal
        {
            UNKNOWN = -1,
            NO,
            YES
        };
        enum TimeFields
        {
            SECONDS  = 1 << 0,
            MINUTES  = 1 << 1,
            HOURS    = 1 << 2,
            MONTHDAY = 1 << 3,
            MONTH    = 1 << 4,
            YEAR     = 1 << 5
        };

    private:
    
        TimeType    d_type; // current type of info in d_tm member
                            // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone)                   // (LOCALTIME (implied when using displayZone