Explorar el Código

Add tests and remove date-time boost library

Eric Ramat hace 7 años
padre
commit
4132164341

+ 1 - 1
CMakeLists.txt

@@ -100,7 +100,7 @@ ENDIF (WIN32)
 SET(Boost_DETAILED_FAILURE_MSG FALSE)
 SET(Boost_DEBUG FALSE)
 
-FIND_PACKAGE(Boost COMPONENTS date_time serialization system)
+FIND_PACKAGE(Boost COMPONENTS serialization system)
 #IF (Boost_MINOR_VERSION AND ${Boost_MINOR_VERSION} LESS "35")
 #  SET(Boost_SYSTEM_LIBRARY "")
 #ENDIF (Boost_MINOR_VERSION AND ${Boost_MINOR_VERSION} LESS "35")

+ 1 - 2
src/artis/kernel/ModelFactory.hpp

@@ -131,8 +131,7 @@ std::once_flag artis::kernel::ModelFactory < M, I, O >::_flag;
     public:                                                             \
     creator_##mdl()                                                     \
         {                                                               \
-            bool r = fct::factory().add(fct::factory().make_id(),       \
-                                        this);                          \
+            fct::factory().add(fct::factory().make_id(), this);         \
         }                                                               \
     std::string get() const                                             \
         { return boost::core::demangle(typeid(mdl).name()); }           \

+ 1 - 2
src/artis/utils/CMakeLists.txt

@@ -10,8 +10,7 @@ SET(ARTIS_UTILS_CPP DateTime.cpp ParametersReader.cpp)
 SET(ARTIS_UTILS_HPP DateTime.hpp DoubleTime.hpp Exception.hpp
   ParametersReader.hpp Time.hpp Trace.hpp)
 
-ADD_LIBRARY(artis-utils SHARED ${ARTIS_UTILS_CPP}
-  ${ARTIS_UTILS_HPP})
+ADD_LIBRARY(artis-utils SHARED ${ARTIS_UTILS_CPP} ${ARTIS_UTILS_HPP})
 
 TARGET_LINK_LIBRARIES(artis-utils ${Boost_LIBRARIES})
 

+ 642 - 0
src/artis/utils/DateTime.cpp

@@ -22,6 +22,648 @@
 
 #include <artis/utils/DateTime.hpp>
 
+#include <sstream>
+#include <regex>
+#include <ctime>
+#include <cmath>
+
 namespace artis { namespace utils {
 
+bool intern_isLeapYear(long year) noexcept
+{
+    if (year % 4 != 0)
+	return false;
+
+    if (year % 100 != 0)
+	return true;
+
+    if (year % 400 != 0)
+	return false;
+
+    return true;
+}
+
+long intern_aYear(long year) noexcept
+{
+    if (intern_isLeapYear(year))
+	return 366;
+
+    return 365;
+}
+
+long intern_aMonth(long year, long month) noexcept
+{
+    switch (month) {
+	case 1: return 31;
+	case 2:
+	if (intern_isLeapYear(year))
+            return 29;
+        return 28;
+	case 3: return 31;
+	case 4: return 30;
+	case 5: return 31;
+	case 6: return 30;
+	case 7: return 31;
+	case 8: return 31;
+	case 9: return 30;
+	case 10: return 31;
+	case 11: return 30;
+	case 12: return 31;
+	default:
+	    return std::numeric_limits<long>::min();
+    }
+}
+
+struct intern_date
+{
+    long myear;
+    long mmonth;
+    long mday;
+    long mhours;
+    long mminutes;
+    long mseconds;
+
+    enum STR_FORMAT
+    {
+	extended, //"%Y-%m-%d %H:%M:%S"
+	ymd,      //"%Y-%m-%d"
+	hms       //"%H:%M:%S"
+    };
+
+    intern_date() noexcept
+	: myear(1400)
+	, mmonth(1)
+	, mday(1)
+	, mhours(0)
+	, mminutes(0)
+	, mseconds(0)
+    {
+    }
+
+    intern_date(long year, long month, long day, double partofday) noexcept
+	: myear(year)
+	, mmonth(month)
+	, mday(day)
+	, mhours(0)
+	, mminutes(0)
+	, mseconds(0)
+    {
+	initPartOfDay(partofday);
+    }
+
+    intern_date(const intern_date& d) = default;
+    intern_date& operator=(const intern_date& d) = default;
+    intern_date(intern_date&& d) = default;
+    intern_date& operator=(intern_date&& d) = default;
+
+    void initPartOfDay(double partofday) noexcept //between 0 and 1
+    {
+	double f = partofday * 24.0;
+	mhours = std::floor(f);
+	f -= mhours;
+
+	f *= 60.0;
+	mminutes = std::floor(f);
+	f -= mminutes;
+
+	f *= 60.0;
+	mseconds = std::floor(f);
+    }
+
+    std::string toString(STR_FORMAT fmt) noexcept
+    {
+	std::stringstream ss;
+
+	if (fmt != hms) {
+	    ss << myear << "-";
+	    if (mmonth < 10) {
+		ss << "0";
+	    }
+	    ss << mmonth << "-";
+	    if (mday < 10) {
+		ss << "0";
+	    }
+	    ss << mday ;
+	}
+	if (fmt == extended) {
+	    ss << " ";
+	}
+	if (fmt != ymd) {
+	    if (mhours < 10) {
+		ss << "0";
+	    }
+	    ss << mhours << ":";
+	    if (mminutes < 10) {
+		ss << "0";
+	    }
+	    ss << mminutes << ":";
+	    if (mseconds < 10) {
+		ss << "0";
+	    }
+	    ss << mseconds;
+
+	}
+
+	return ss.str();
+    }
+
+    //format : not extended = "%Y-%m-%d"
+    //         extended     = "%Y-%m-%d %H:%M:%S"
+    //return true if no error
+    bool fromString(const std::string& date, STR_FORMAT toparse) noexcept
+    {
+	bool error = false;
+
+	if (toparse == extended) {
+	    //parse "%Y-%m-%d %H:%M:%S"
+	    try {
+		std::regex regex("([^\\s]+)\\s([^\\s]+)");
+		std::sregex_iterator next(date.begin(), date.end(), regex);
+		std::sregex_iterator end;
+
+		if (next != end) {
+
+		    std::smatch match = *next;
+
+		    if (match.size() == 3) {
+			fromString(match[1].str(), ymd);
+			fromString(match[2].str(), hms);
+		    } else {
+			error = true;
+		    }
+
+		} else {
+		    error =true;
+		}
+	    } catch (const std::exception& e ){
+		error = true;
+	    }
+	} else {
+	    //parse "%Y-%m-%d" or "%H:%M:%S"
+	    unsigned int nbmatches = 0;
+	    try {
+		std::regex regex("[0-9]+|[^0-9]");
+		std::sregex_iterator next(date.begin(), date.end(), regex);
+		std::sregex_iterator end;
+		while (next != end) {
+		    std::smatch match = *next;
+		    nbmatches++;
+		    if (nbmatches == 1) {
+			if (toparse == ymd) {
+			    myear = std::stol(match.str());
+			} else {
+			    mhours = std::stol(match.str());
+			}
+		    } else if (nbmatches == 3) {
+			if (toparse == ymd) {
+			    mmonth = std::stol(match.str());
+			} else {
+			    mminutes = std::stol(match.str());
+			}
+		    } else if (nbmatches == 5) {
+			if (toparse == ymd) {
+			    mday = std::stol(match.str());
+			} else {
+			    mseconds = std::stol(match.str());
+			}
+		    }
+		    next++;
+		}
+	    } catch (const std::exception& e ){
+		error = true;
+	    }
+	    error = error or (nbmatches != 5);
+	}
+	return error;
+    }
+
+    //init from julian day eg: 2454115.05486
+    void fromJulianDay(double julianDay) noexcept
+    {
+
+	double partofday, J;
+	partofday = std::modf(julianDay, &J);
+
+	initPartOfDay(partofday);
+
+	//parameters for gregorian calendar (cf wikipedia)
+	int y=4716;
+	int j=1401;
+	int m=2;
+	int n=12;
+	int r=4;
+	int p=1461;
+	int v=3;
+	int u=5;
+	int s=153;
+	int w=2;
+	int B=274277;
+	int C=-38;
+
+	long f = J + j + (((4 * J + B) / 146097) * 3) / 4 + C;
+	long e = r * f + v;
+	long g = (e % p) / r;
+	long h = u * g + w;
+	mday = (h % s) / u + 1;
+	mmonth = ((h / s + m) % n) + 1;
+	myear = (e / p) - y + (n + m - mmonth) / n;
+    }
+
+    bool equals(const intern_date& d) const noexcept
+    {
+	return (myear == d.myear and mmonth == d.mmonth and mday == d.mday);
+    }
+
+    bool inf(const intern_date& d) const noexcept
+    {
+	if (myear < d.myear)
+	    return true;
+
+	if (myear > d.myear)
+	    return false;
+
+	if (mmonth < d.mmonth)
+	    return true;
+
+	if (mmonth > d.mmonth)
+	    return false;
+
+	return mday < d.mday;
+    }
+
+    bool sup(const intern_date& d) const noexcept
+    {
+	if (myear < d.myear)
+	    return false;
+
+	if (myear > d.myear)
+	    return true;
+
+	if (mmonth < d.mmonth)
+	    return false;
+
+	if (mmonth > d.mmonth)
+	    return true;
+
+	return mday > d.mday;
+    }
+
+    //tells if a date is valid
+    bool isValid() const noexcept
+    {
+	if (1 > mmonth or mmonth > 12)
+	    return false;
+
+	if (1 > mday or mday > intern_aMonth(myear, mmonth))
+	    return false;
+
+	if (0 > mhours or mhours > 23)
+	    return false;
+
+	if (0 > mminutes or mminutes > 60)
+	    return false;
+
+	if (0 > mseconds or mseconds > 60)
+	    return false;
+
+	return true;
+    }
+
+    //add months to the current date
+    void addMonths(unsigned int months) noexcept
+    {
+	mmonth += months;
+	while (mmonth > 12) {
+	    myear ++;
+	    mmonth -= 12;
+	    long nbDaysInMonth = intern_aMonth(mmonth, myear);
+	    if (mday > nbDaysInMonth) {
+		mmonth ++;
+		mday -= nbDaysInMonth;
+	    }
+	}
+    }
+
+    //daynNumber as computed in boost gregorian calendar.. (in wikipedia)
+    //12h Jan 1, 4713 BC (-4713-01-BC)
+    long julianDayNumber() const noexcept
+    {
+	unsigned short a = static_cast<unsigned short>((14-mmonth)/12);
+	unsigned short y = static_cast<unsigned short>(myear + 4800 - a);
+	unsigned short m = static_cast<unsigned short>(mmonth + 12*a - 3);
+
+	return mday+((153*m+2)/5)+365*y+(y/4)-(y/100)+(y/400)-32045;
+    }
+
+    double julianDay() const noexcept
+    {
+	double res = static_cast<double>(julianDayNumber());
+	res += mhours/24.0;
+	res += mminutes/1440.0;
+	res += mseconds/86400.0;
+	return res;
+    }
+
+    //day of the year (1<>366)
+    long dayOfyear() const noexcept
+    {
+	long ret = 0;
+
+	for (long m = 1; m < mmonth; m++)
+	    ret += intern_aMonth(myear, m);
+
+	ret += mday;
+
+	return ret;
+    }
+
+    //days between a date and end of year (1<>366)
+    long daysUntilEndOfyear() const noexcept
+    {
+	return intern_aYear(myear) - dayOfyear();
+    }
+
+    //from boost date-time library
+    unsigned short dayOfWeek() noexcept
+    {
+	unsigned short a = static_cast<unsigned short>((14-mmonth)/12);
+	unsigned short y = static_cast<unsigned short>(myear - a);
+	unsigned short m = static_cast<unsigned short>(mmonth + 12*a - 2);
+	unsigned short d = static_cast<unsigned short>(
+		(mday + y + (y/4) - (y/100) + (y/400) + (31*m)/12) % 7);
+
+	return d;
+    }
+
+    //from boost date-time library
+    unsigned short weekOfYear() noexcept
+    {
+	unsigned long julianbegin = intern_date(myear, 1, 1, 0).julianDay();
+	unsigned long juliantoday = julianDay();
+	unsigned long day = (julianbegin + 3) % 7;
+	unsigned long week = (juliantoday + day - julianbegin + 4)/7;
+
+	if ((week >= 1) && (week <= 52))
+	    return week;
+
+	if (week == 53) {
+	    if((day==6) ||(day == 5 && intern_isLeapYear(myear))) {
+		return week; //under these circumstances week == 53.
+	    } else {
+		return 1; //monday - wednesday is in week 1 of next year
+	    }
+	}
+	//if the week is not in current year recalculate using the previous
+	//year as the beginning year
+	else if (week == 0) {
+	    julianbegin = intern_date(myear-1, 1, 1, 0).julianDay();
+	    day = (julianbegin + 3) % 7;
+	    week = (juliantoday + day - julianbegin + 4)/7;
+	    return week;
+	}
+
+	return week;  //not reachable -- well except
+	// if day == 5 and is_leap_year != true
+    }
+
+    //days between a date and end of month (0<>31)
+    long idaysUntilEndOfMonth() const noexcept
+    {
+	return intern_aMonth(myear, mmonth)-mday;
+    }
+
+    //nb days between two dates (negative if this is before)
+    long daysUntil(const intern_date& d) const noexcept
+    {
+	if (equals(d))
+	    return 0;
+
+	if (sup(d))
+	    return -d.daysUntil(*this);
+
+	return d.julianDay() - julianDay();
+    }
+};
+
+
+//output format `2011-Jun-09 12:13:21'
+std::string DateTime::currentDate()
+{
+    time_t rawtime;
+    struct tm * timeinfo;
+
+    time (&rawtime);
+    timeinfo = localtime(&rawtime);
+
+    static const char mon_name[][4] = {
+	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+    };
+
+    char result[26];
+    sprintf(result, "%d-%.3s-%d %.2d:%.2d:%.2d \n",
+	    1900 + timeinfo->tm_year,
+	    mon_name[timeinfo->tm_mon],
+	    timeinfo->tm_mday,
+	    timeinfo->tm_hour,
+	    timeinfo->tm_min, timeinfo->tm_sec);
+
+    return result;
+}
+
+unsigned int DateTime::year(double time)
+{
+    intern_date d;
+    d.fromJulianDay(time);
+    return d.myear;
+}
+
+unsigned int DateTime::month(double time)
+{
+    intern_date d;
+    d.fromJulianDay(time);
+    return d.mmonth;
+}
+
+unsigned int DateTime::dayOfMonth(double time)
+{
+    intern_date d;
+    d.fromJulianDay(time);
+    return d.mday;
+}
+
+unsigned int DateTime::dayOfWeek(double time)
+{
+    intern_date d;
+    d.fromJulianDay(time);
+    return d.dayOfWeek();
+}
+
+unsigned int DateTime::dayOfYear(double time)
+{
+    intern_date d;
+    d.fromJulianDay(time);
+    return d.dayOfyear();
+}
+
+unsigned int DateTime::weekOfYear(double time)
+{
+    intern_date d;
+    d.fromJulianDay(time);
+    return d.weekOfYear();
+}
+
+/*  - - - - - - - - - - - - - --ooOoo-- - - - - - - - - - - -  */
+
+bool DateTime::isLeapYear(double time)
+{
+    intern_date d;
+    d.fromJulianDay(time);
+    return intern_isLeapYear(d.myear);;
+}
+
+/*  - - - - - - - - - - - - - --ooOoo-- - - - - - - - - - - -  */
+
+double DateTime::aYear(double time)
+{
+    return isLeapYear(time) ? 366 : 365;
+}
+
+double DateTime::aMonth(double time)
+{
+    intern_date d;
+    d.fromJulianDay(time);
+    return(intern_aMonth(d.myear, d.mmonth));
+
+}
+
+double DateTime::years(double time, unsigned int n)
+{
+
+    intern_date d1;
+    d1.fromJulianDay(time);
+    intern_date d2(d1);
+    d2.myear += n;
+    return d2.julianDay() - d1.julianDay();
+}
+
+double DateTime::months(double time, unsigned int n)
+{
+
+    intern_date d1;
+    d1.fromJulianDay(time);
+    intern_date d2(d1);
+    d2.addMonths(n);
+    return d2.julianDay() - d1.julianDay();
+}
+
+DateTimeUnitOptions DateTime::convertUnit(const std::string& unit)
+{
+    if (unit == "day") {
+	return DATE_TIME_UNIT_DAY;
+    } else if (unit == "week") {
+	return DATE_TIME_UNIT_WEEK;
+    } else if (unit == "month") {
+	return DATE_TIME_UNIT_MONTH;
+    } else if (unit == "year") {
+	return DATE_TIME_UNIT_YEAR;
+    } else {
+	return DATE_TIME_UNIT_DAY;
+    }
+}
+
+double DateTime::duration(double time, double duration,
+	DateTimeUnitOptions unit)
+{
+    switch (unit) {
+	case DATE_TIME_UNIT_NONE:
+	case DATE_TIME_UNIT_DAY:
+	    return days(duration);
+	case DATE_TIME_UNIT_WEEK:
+	    return weeks(duration);
+	case DATE_TIME_UNIT_MONTH:
+	    return months(time, duration);
+	case DATE_TIME_UNIT_YEAR:
+	    return years(time, duration);
+    }
+    return 0;
+}
+
+std::string DateTime::toJulianDayNumber(unsigned long date)
+{
+    intern_date d;
+    d.fromJulianDay(static_cast<double>(date));
+    return d.toString(intern_date::ymd);
+}
+
+
+//parsing "2001-10-9"
+long DateTime::toJulianDayNumber(const std::string& date)
+{
+    intern_date d;
+    d.fromString(date, intern_date::ymd);
+    return d.julianDayNumber();
+}
+
+
+std::string DateTime::toJulianDay(double date)
+{
+    intern_date d;
+    d.fromJulianDay(date);
+    return d.toString(intern_date::extended);
+}
+
+
+// parsing "2001-10-9 hh:mm:ss"
+double DateTime::toJulianDay(const std::string& date)
+{
+
+    intern_date d;
+    d.fromString(date, intern_date::extended);
+    return d.julianDay();
+}
+
+
+
+bool DateTime::isValidYear(double date)
+{
+    intern_date d;
+    d.fromJulianDay(date);
+    bool valid = (1399 < d.myear and d.myear < 10000);//boost rule ?
+    return valid;
+}
+
+double DateTime::toTime(double date, long& year,
+	long& month, long& day,
+	long& hours, long& minutes,
+	long& seconds)
+{
+    intern_date d;
+    d.fromJulianDay(date);
+    year = d.myear;
+    month = d.mmonth;
+    day = d.mday;
+
+    hours = d.mhours;
+    minutes = d.mminutes;
+    seconds = d.mseconds;
+
+    return 0.0;
+}
+
+void DateTime::currentDate(long& year,
+	long& month,
+	long& day)
+{
+
+    time_t rawtime;
+    struct tm * timeinfo;
+
+    time (&rawtime);
+    timeinfo = localtime (&rawtime);
+    year = timeinfo->tm_year;
+    month = timeinfo->tm_mon;
+    day = timeinfo->tm_mday;
+}
+
 } }

+ 270 - 115
src/artis/utils/DateTime.hpp

@@ -37,124 +37,279 @@
 
 namespace artis { namespace utils {
 
+enum DateTimeUnitOptions
+{
+    DATE_TIME_UNIT_NONE,
+    DATE_TIME_UNIT_DAY,
+    DATE_TIME_UNIT_WEEK,
+    DATE_TIME_UNIT_MONTH,
+    DATE_TIME_UNIT_YEAR
+};
+
 class DateTime
 {
 public:
-    static std::string currentDate()
-    {
-        boost::posix_time::ptime current(
-            boost::posix_time::second_clock::local_time());
-
-        std::ostringstream out;
-        out << current;
-
-        return out.str();
-    }
-
-    static unsigned int year(const double& time)
-    {
-        boost::gregorian::date d(
-            boost::numeric_cast <
-                boost::gregorian::date::date_int_type >(time));
-
-        return d.year();
-    }
-
-    static unsigned int month(const double& time)
-    {
-        boost::gregorian::date d(
-            boost::numeric_cast <
-                boost::gregorian::date::date_int_type >(time));
-
-        return d.month();
-    }
-
-    static unsigned int dayOfMonth(const double& time)
-    {
-        boost::gregorian::date d(
-            boost::numeric_cast <
-                boost::gregorian::date::date_int_type >(time));
-
-        return d.day();
-    }
-
-    static unsigned int dayOfYear(const double& time)
-    {
-        boost::gregorian::date d(
-            boost::numeric_cast <
-                boost::gregorian::date::date_int_type >(time));
-
-        return d.day_of_year();
-    }
-
-    static unsigned int weekOfYear(const double& time)
-    {
-        boost::gregorian::date d(
-            boost::numeric_cast <
-                boost::gregorian::date::date_int_type >(time));
-
-        return d.week_number();
-    }
-
-    static long toJulianDayNumber(int year, int month, int day)
-    {
-        std::ostringstream oss;
-        oss << year << '-' << month << '-' << day;
-        return toJulianDayNumber(oss.str());
-    }
-
-    static long toJulianDayNumber(const std::string& date)
-    {
-        boost::gregorian::date d;
-
-        try {
-            d = boost::gregorian::from_simple_string(date);
-            return d.julian_day();
-        } catch (...) {
-            try {
-                d = boost::gregorian::from_undelimited_string(date);
-                return d.julian_day();
-            } catch (...) {
-                throw utils::ParseError(
-                    boost::format(
-                        "Date time error: error to convert '%1%' into julian"
-                        " day number") % date);
-            }
-        }
-        return -1.0;
-    }
-
-    static std::string toJulianDay(double date)
-    {
-        double f, e;
-        f = std::modf(date, &e);
-
-        f *= 24.0;
-        long hours = std::floor(f);
-        f -= hours;
-
-        f *= 60.0;
-        long minutes = std::floor(f);
-        f -= minutes;
-
-        f *= 60.0;
-        long seconds = std::floor(f);
-        f -= seconds;
-
-        boost::posix_time::time_duration td(hours, minutes, seconds, f);
-        boost::posix_time::ptime d(boost::gregorian::date(e), td);
-        return boost::posix_time::to_simple_string(d);
-    }
-
-    static void format_date(const std::string& str, std::string& date)
-    {
-        std::vector < std::string > list;
-
-        boost::split(list, str, boost::is_any_of("-"));
-        date = (boost::format("%1%/%2%/%3%") % list[2] % list[1] %
-                list[0]).str();
-    }
-
+    /**
+     * @brief Write the current date and time conform to RFC 822.
+     * @code
+     * std::cout << "currentDate(): `"
+     *           << vle::utils::DateTime::currentDate()
+     *           << "'\n";
+     *
+     * // Display: currentDate(): `2011-Jun-09 12:13:21'
+     * @endcode
+     * @return string representation of date.
+     */
+    static std::string currentDate();
+
+                                  /* * * * */
+
+    /**
+     * @brief Get the year in the simulation time.
+     * @code
+     * vle::utils::DateTime::year(2451545) == 2000u;
+     * @endcode
+     * @param time The simulation time.
+     * @return An unsigned int.
+     */
+    static unsigned int year(double time);
+
+    /**
+     * @brief Get the month in the simulation time.
+     * @code
+     * vle::utils::DateTime::month(2451545) == 1u;
+     * @endcode
+     * @param time The simulation time.
+     * @return An unsigned int.
+     */
+    static unsigned int month(double time);
+
+    /**
+     * @brief Get the day of the month in the simulation time.
+     * @code
+     * vle::utils::DateTime::dayOfMonth((2451545)) == 1u;
+     * @endcode
+     * @param time The simulation time.
+     * @return An unsigned int.
+     */
+    static unsigned int dayOfMonth(double time);
+
+    /**
+     * @brief Get the day in the week of the simulation time.
+     * @code
+     * vle::utils::DateTime::dayOfWeek((2451545)) == 6u;
+     * @endcode
+     * @param time The simulation time.
+     * @return An unsigned int.
+     */
+    static unsigned int dayOfWeek(double time);
+
+    /**
+     * @brief Get the day in the year of the simulation time.
+     * @code
+     * vle::utils::DateTime::dayOfYear((2451545)) == 1u;
+     * @endcode
+     * @param time The simulation time.
+     * @return An unsigned int.
+     */
+    static unsigned int dayOfYear(double time);
+
+    /**
+     * @brief Get the week in the year of the simulation time.
+     * @code
+     * vle::utils::DateTime::dayOfYear((2451545)) == 1u;
+     * @endcode
+     * @param time The simulation time.
+     * @return An unsigned int.
+     */
+    static unsigned int weekOfYear(double time);
+
+    /**
+     * @brief Check if the simulation time is a leap year.
+     * @param time The simulation time.
+     * @return true if time is a leap year, false otherwise.
+     */
+    static bool isLeapYear(double time);
+
+    /**
+     * @brief Get the number of day in the year for the simulaton time.
+     * @code
+     * vle::utils::Datime::aYear(2451545) == 366;
+     * @endcode
+     * @param time The simulation time.
+     * @return number of day.
+     */
+    static double aYear(double time);
+
+    /**
+     * @brief Get the number of day in the month for the simulation time.
+     * @code
+     * vle::utils::Datime::aMonth(2451545) == 31;
+     * vle::utils::Datime::aMonth(2451576) == 29;
+     * @endcode
+     * @param time The simulation time.
+     * @return number of day.
+     */
+    static double aMonth(double time);
+
+    /**
+     * @brief Get the number of day in a week.
+     * @return Return 7.
+     */
+    static inline double aWeek() { return 7; }
+
+    /**
+     * @brief Get the number of day in a day.
+     * @return Return 1.
+     */
+    static inline double aDay() { return 1; }
+
+    /**
+     * @brief Get number of days in n-years from the simulation time.
+     * @code
+     * vle::utils::DateTime::years((2451545), 1), 366);
+     * vle::utils::DateTime::years((2451545), 2), 731);
+     * @endcode
+     * @param time The simulation time.
+     * @param n The number of years.
+     * @return The number of days in n-years.
+     */
+    static double years(double time, unsigned int n);
+
+    /**
+     * @brief Get number of days in n-months from the simulation time.
+     * @code
+     * vle::utils::DateTime::months((2451545), 2) = 60;
+     * @endcode
+     * @param time The simulation time.
+     * @param n The number of weeks.
+     * @return The number of days in n-months.
+     */
+    static double months(double time, unsigned int n);
+
+    /**
+     * @brief Get number of days in n-weeks.
+     * @param n Number of weeks.
+     * @return n * 7.
+     */
+    static inline double weeks(unsigned int n) { return (int)(7 * n); }
+
+    /**
+     * @brief Get number of days in n-days.
+     * @param n Number of days.
+     * @return n.
+     */
+    static inline double days(unsigned int n) { return (int)n; }
+
+    /**
+     * @brief Convert std::string unit ("day", "week", "month", "year") into
+     * the DateTime::Unit type.
+     * @param unit The std::string unit to convert.
+     * @return The convertion of Day if error.
+     */
+    static DateTimeUnitOptions convertUnit(const std::string& unit);
+
+    /**
+     * @brief A easy function to call days(), weeks(), months() or years()
+     * using a DateTime::Unit type.
+     * @param time The simulation date (useless for Day, Week).
+     * @param duration The number of DateTime::Unit.
+     * @param unit The unit.
+     * @return A number of day.
+     */
+    static double duration(double time,
+                           double duration,
+                           DateTimeUnitOptions unit);
+
+                                  /* * * * */
+
+    /**
+     * @brief Convert an julian day number into a string.
+     * @code
+     * vle::utils::DateTime::toJulianDayNumber(2452192) = "2001-10-9";
+     * @endcode
+     * @param date The date to convert.
+     * @return A string representation of the julian day.
+     */
+    static std::string toJulianDayNumber(unsigned long date);
+
+    /**
+     * @brief Convert a string into a julian day number;
+     * @code
+     * vle::utils::DateTime::toJulianDayNumber("2001-10-9") = 2452192;
+     * @endcode
+     * @param date The date to convert.
+     * @return A julian day number.
+     */
+    static long toJulianDayNumber(const std::string& date);
+
+    /**
+     * @brief Convert a julian date into a string.
+     * @code
+     * vle::utils::DateTime::toJulianDay(2454115.05486)) = "2001-10-9 hh:mm:ss";
+     * @endcode
+     * @param date The date to convert.
+     * @return A string representation of the julian day.
+     */
+    static std::string toJulianDay(double date);
+
+    /**
+     * @brief Convert a string into a julian day.
+     * @code
+     * vle::utils::DateTime::toJulianDay("2001-10-9 hh:mm:ss") = 2454115.05486;
+     * @endcode
+     * @param date The date to convert.
+     * @return A string representation of the julian day.
+     */
+    static double toJulianDay(const std::string& date);
+
+                                  /* * * * */
+
+    /**
+     * @brief Check if the date is a valid year in gregorian calendard.
+     *
+     * @param date The date to check.
+     *
+     * @return True if date is a valid year, false otherwise.
+     */
+    static bool isValidYear(double date);
+
+    /**
+     * @brief Explode the specified date attribute to year, month, day in the
+     * month, hours, minutes and seconds.
+     *
+     * @param date The date to convert.
+     * @param year Output parameter to represent year.
+     * @param month Output parameter to represent month.
+     * @param day Output parameter to represent day in a month (1..31).
+     * @param hours Output parameter to represent hours in date.
+     * @param minutes Output parameter to represent minutes in date.
+     * @param seconds Output parameter to represent seconds in date.
+     *
+     * @throw utils::ArgError error to convert the date.
+     *
+     * @return The remainder of the conversion.
+     */
+    static double toTime(double date,
+                         long& year,
+                         long& month,
+                         long& day,
+                         long& hours,
+                         long& minutes,
+                         long& seconds);
+
+    /**
+     * @brief Explode current date to year, month, day in the
+     * month, hours, minutes and seconds.
+     *
+     * @param year Output parameter to represent year.
+     * @param month Output parameter to represent month.
+     * @param day Output parameter to represent day in a month (1..31).
+     *
+     */
+    static void currentDate(long& year,
+                            long& month,
+                            long& day);
 };
 
 } }

+ 7 - 1
src/test/CMakeLists.txt

@@ -1,6 +1,5 @@
 INCLUDE_DIRECTORIES(
   ${CMAKE_SOURCE_DIR}/src
-  ${ECOMERISTEM_INCLUDE_DIRS}
   ${Boost_INCLUDE_DIRS})
 
 LINK_DIRECTORIES()
@@ -11,3 +10,10 @@ TARGET_LINK_LIBRARIES(artis-tests artis-kernel artis-observer artis-utils
   ${Boost_LIBRARIES})
 
 INSTALL(TARGETS artis-tests DESTINATION bin)
+
+ADD_EXECUTABLE(artis-meta test2.cpp)
+
+TARGET_LINK_LIBRARIES(artis-meta artis-kernel artis-observer artis-utils
+  ${Boost_LIBRARIES})
+
+INSTALL(TARGETS artis-meta DESTINATION bin)

+ 204 - 0
src/test/models.hpp

@@ -0,0 +1,204 @@
+/**
+ * @file test/models.hpp
+ * @author See the AUTHORS file
+ */
+
+/*
+ * Copyright (C) 2012-2017 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <artis/kernel/AbstractAtomicModel.hpp>
+#include <artis/kernel/AbstractCoupledModel.hpp>
+#include <artis/utils/Trace.hpp>
+
+#include <memory>
+
+#ifndef TEST_MODELS_HPP
+#define TEST_MODELS_HPP
+
+struct GlobalParameters
+{ };
+
+struct ModelParameters
+{ };
+
+using Model = artis::kernel::AbstractModel < artis::utils::DoubleTime,
+                                             ModelParameters >;
+
+using Trace = artis::utils::Trace < artis::utils::DoubleTime >;
+using TraceElement = artis::utils::TraceElement < artis::utils::DoubleTime >;
+
+template < typename T >
+using AtomicModel = artis::kernel::AbstractAtomicModel <
+    T, artis::utils::DoubleTime, ModelParameters >;
+
+template < typename T >
+using CoupledModel = artis::kernel::AbstractCoupledModel <
+    T, artis::utils::DoubleTime, ModelParameters, GlobalParameters >;
+
+class AModel : public AtomicModel < AModel >
+{
+public:
+    enum externals { };
+
+    enum internals { DX, BX, IX };
+
+    AModel()
+    {
+        internal(IX, &AModel::_ix);
+        internal(BX, &AModel::_bx);
+        internal(DX, &AModel::_dx);
+    }
+
+    virtual ~AModel()
+    { }
+
+    void compute(double t, bool /* update */)
+    {
+        ++_ix;
+        _bx = not _bx;
+        ++_dx;
+
+        ::Trace::trace() << ::TraceElement("A", t, artis::utils::COMPUTE);
+        ::Trace::trace().flush();
+
+    }
+
+    void init(double /* t */, const ModelParameters& /* parameters */)
+    {
+        _ix = 0;
+        _bx = false;
+        _dx = 0.;
+    }
+
+private:
+    int _ix;
+    bool _bx;
+    double _dx;
+};
+
+class BModel : public AtomicModel < BModel >
+{
+public:
+    enum externals { IX, BX, DX };
+    enum internals { IY, BY, DY };
+    enum states { N };
+
+    BModel()
+    {
+        // external(IX, &BModel::_ix);
+        E < int >({ { IX, &BModel::_ix } });
+
+        external(BX, &BModel::_bx);
+        external(DX, &BModel::_dx);
+
+        // internal(IY, &BModel::_iy);
+        I < int >({ { IY, &BModel::_iy } });
+
+        internal(BY, &BModel::_by);
+        internal(DY, &BModel::_dy);
+
+        S < int >({ { N, &BModel::_n } });
+    }
+
+    virtual ~BModel()
+    { }
+
+    void compute(double t, bool /* update */)
+    {
+        _iy = _ix + 1;
+        _by = not _bx;
+        _dy = _dx + 1;
+        ++_n;
+
+        ::Trace::trace() << ::TraceElement("B", t, artis::utils::COMPUTE);
+        ::Trace::trace().flush();
+
+    }
+
+    void init(double /* t */, const ModelParameters& /* parameters */)
+    {
+        _iy = 0;
+        _by = false;
+        _dy = 0.;
+        _n = 0;
+    }
+
+private:
+    // externals
+    int _ix;
+    bool _bx;
+    double _dx;
+
+    // internals
+    int _iy;
+    bool _by;
+    double _dy;
+
+    // states
+    int _n;
+};
+
+class RootModel : public CoupledModel < RootModel >
+{
+public:
+    enum submodels { A, B };
+    enum states { N };
+
+    RootModel() : _a(new AModel), _b(new BModel)
+    {
+        // submodels
+        S({ { A, _a.get() }, { B, _b.get() } });
+
+        // states
+        S < int >({ { N, &RootModel::_n } });
+    }
+
+    virtual ~RootModel()
+    { }
+
+    void compute(double t, bool /* update */)
+    {
+        (*_a)(t);
+        _b->put < double >(t, BModel::DX, _a->get < double >(t, AModel::DX));
+        _b->put < int >(t, BModel::IX, _a->get < int >(t, AModel::IX));
+        _b->put < bool >(t, BModel::BX, _a->get < bool >(t, AModel::BX));
+        (*_b)(t);
+
+        ++_n;
+
+        ::Trace::trace() << ::TraceElement("ROOT", t, artis::utils::COMPUTE);
+        ::Trace::trace().flush();
+
+    }
+
+    void init(double t, const ModelParameters& parameters)
+    {
+        _a->init(t, parameters);
+        _b->init(t, parameters);
+        _n = 0;
+    }
+
+private:
+    // submodels
+    std::unique_ptr < AModel > _a;
+    std::unique_ptr < BModel > _b;
+
+    // states
+    int _n;
+};
+
+#endif

+ 51 - 358
src/test/test.cpp

@@ -23,200 +23,22 @@
 //#define CATCH_CONFIG_MAIN
 //#include <test/catch.hpp>
 
-#include <artis/kernel/AbstractAtomicModel.hpp>
-#include <artis/kernel/AbstractCoupledModel.hpp>
-//#include <artis/kernel/Builder.hpp>
+#include <test/models.hpp>
+
+#include <artis/kernel/Builder.hpp>
 #include <artis/kernel/ModelFactory.hpp>
 #include <artis/kernel/Simulator.hpp>
 #include <artis/observer/Output.hpp>
 
 #include <artis/utils/DateTime.hpp>
-#include <artis/utils/Trace.hpp>
-
-#include <memory>
-
-struct GlobalParameters
-{ };
-
-struct ModelParameters
-{ };
 
 using namespace artis::kernel;
-using namespace artis::utils;
 
-using Model = AbstractModel < DoubleTime, ModelParameters >;
 using Creator = ObjectCreator < Model >;
 using Factory = ModelFactory < Model, int, Creator >;
 
-using Trace = Trace < DoubleTime >;
-using TraceElement = TraceElement < DoubleTime >;
-
-template < typename T >
-using AtomicModel = AbstractAtomicModel < T, DoubleTime, ModelParameters >;
-
-template < typename T >
-using CoupledModel = AbstractCoupledModel < T, DoubleTime, ModelParameters,
-                                            GlobalParameters >;
-
-class AModel : public AtomicModel < AModel >
-{
-public:
-    enum externals { };
-
-    enum internals { DX, BX, IX };
-
-    AModel()
-    {
-        internal(IX, &AModel::_ix);
-        internal(BX, &AModel::_bx);
-        internal(DX, &AModel::_dx);
-    }
-
-    virtual ~AModel()
-    { }
-
-    void compute(double t, bool /* update */)
-    {
-        ++_ix;
-        _bx = not _bx;
-        ++_dx;
-
-        ::Trace::trace() << ::TraceElement("A", t, COMPUTE);
-        ::Trace::trace().flush();
-
-    }
-
-    void init(double /* t */, const ModelParameters& /* parameters */)
-    {
-        _ix = 0;
-        _bx = false;
-        _dx = 0.;
-    }
-
-private:
-    int _ix;
-    bool _bx;
-    double _dx;
-};
-
 DECLARE_MODEL(AModel, ::Model, ::Factory);
-
-class BModel : public AtomicModel < BModel >
-{
-public:
-    enum externals { IX, BX, DX };
-    enum internals { IY, BY, DY };
-    enum states { N };
-
-    BModel()
-    {
-        // external(IX, &BModel::_ix);
-        E < int >({ { IX, &BModel::_ix } });
-
-        external(BX, &BModel::_bx);
-        external(DX, &BModel::_dx);
-
-        // internal(IY, &BModel::_iy);
-        I < int >({ { IY, &BModel::_iy } });
-
-        internal(BY, &BModel::_by);
-        internal(DY, &BModel::_dy);
-
-        S < int >({ { N, &BModel::_n } });
-    }
-
-    virtual ~BModel()
-    { }
-
-    void compute(double t, bool update)
-    {
-        if (update)
-            std::cout << "UPDATE" << std::endl;
-
-        _iy = _ix + 1;
-        _by = not _bx;
-        _dy = _dx + 1;
-        ++_n;
-
-        ::Trace::trace() << ::TraceElement("B", t, COMPUTE);
-        ::Trace::trace().flush();
-
-    }
-
-    void init(double /* t */, const ModelParameters& /* parameters */)
-    {
-        _iy = 0;
-        _by = false;
-        _dy = 0.;
-        _n = 0;
-    }
-
-private:
-    // externals
-    int _ix;
-    bool _bx;
-    double _dx;
-
-    // internals
-    int _iy;
-    bool _by;
-    double _dy;
-
-    // states
-    int _n;
-};
-
 DECLARE_MODEL(BModel, ::Model, ::Factory);
-
-class RootModel : public CoupledModel < RootModel >
-{
-public:
-    enum submodels { A, B };
-    enum states { N };
-
-    RootModel() : _a(new AModel), _b(new BModel)
-    {
-        // submodels
-        S({ { A, _a.get() }, { B, _b.get() } });
-
-        // states
-        S < int >({ { N, &RootModel::_n } });
-    }
-
-    virtual ~RootModel()
-    { }
-
-    void compute(double t, bool /* update */)
-    {
-        (*_a)(t);
-        _b->put < double >(t, BModel::DX, _a->get < double >(t, AModel::DX));
-        _b->put < int >(t, BModel::IX, _a->get < int >(t, AModel::IX));
-        _b->put < bool >(t, BModel::BX, _a->get < bool >(t, AModel::BX));
-        (*_b)(t);
-
-        ++_n;
-
-        ::Trace::trace() << ::TraceElement("ROOT", t, COMPUTE);
-        ::Trace::trace().flush();
-
-    }
-
-    void init(double t, const ModelParameters& parameters)
-    {
-        _a->init(t, parameters);
-        _b->init(t, parameters);
-        _n = 0;
-    }
-
-private:
-    // submodels
-    std::unique_ptr < AModel > _a;
-    std::unique_ptr < BModel > _b;
-
-    // states
-    int _n;
-};
-
 DECLARE_MODEL(RootModel, ::Model, ::Factory);
 
 typedef artis::kernel::Simulator < RootModel,
@@ -224,11 +46,11 @@ typedef artis::kernel::Simulator < RootModel,
                                    ModelParameters,
                                    GlobalParameters > ASimulator;
 
-// typedef artis::kernel::Builder < ::Factory,
-//                                  RootModel,
-//                                  artis::utils::DoubleTime,
-//                                  ModelParameters,
-//                                  GlobalParameters > ABuilder;
+typedef artis::kernel::Builder < ::Factory,
+                                 RootModel,
+                                 artis::utils::DoubleTime,
+                                 ModelParameters,
+                                 GlobalParameters > ABuilder;
 
 class AView : public artis::observer::View < artis::utils::DoubleTime,
                                              ModelParameters >
@@ -251,183 +73,54 @@ public:
 typedef artis::observer::Output < artis::utils::DoubleTime,
                                   ModelParameters > AnOutput;
 
-struct NullModel : CoupledModel < NullModel >
-{ };
-
-template < typename T >
-struct TType
-{
-    typedef T type;
-
-    T* operator()()
-    { return new T(); }
-};
-
-template < typename P, typename T, typename N /*, typename ST */ > // I, In, Ex, S >
-struct TCoupledModel
-{
-    typename T::type* operator()(P* parent)
-    {
-        //T::type* m = T()();
-        N n;
-        // ST st;
-
-        n(parent);
-        //st(m);
-        return T()();
-    }
-};
-
-// template < T, N, I, ST, In, Ex >
-// class AtomicModel
-// {
-// };
-
-template < typename P >
-struct TNull
-{
-    P* operator()()
-    { return nullptr; }
-};
-
-template < typename T, typename X >
-struct TVariable
-{
-    X T::* variable;
-};
-
-template < typename P, typename N = TNull < P > >
-struct TName
-{
-    void operator()(P* parent)
-    {
-        if (parent) {
-            N n;
-
-            parent->submodel(0, n());
-        }
-    }
-};
-
-// template < typename M, typename N, typename I, typename T >
-// struct TState
-// {
-//     void operator()(M* m)
-//     {
-//         N n;
-
-//     }
-// };
-
-template < typename T, typename M >
-struct TBuilder
-{
-    T* operator()()
-    {
-        M m;
-
-        return m(nullptr);
-    }
-};
-
-// constexpr int AModel::* p = AModel::_ix;
-
-// typedef TBuilder <
-//     RootModel,
-//     TCoupledModel <
-//         NullModel,
-//         TType < RootModel >,
-//         TName < NullModel >/*,
-//         TState <
-//             RootModel,
-//             TName < AModel::_ix >,
-//             TID < AModel::IX >,
-//             TType < int >
-//             > */
-//         >
-//     > ABuilder;
-
-// typedef Builder <
-//     CoupledModel <
-//         Type < RootModel >,
-//         Name < >,
-//         ID < >,
-//         States < >,
-//         Internals < >,
-//         Externals < >,
-//         Submodels <
-//             AtomicModel <
-//                 Type < AModel >,
-//                 Name < RootModel::_a >,
-//                 ID < A >,
-//                 States < >,
-//                 Internals <
-//                     Variable < Name < AModel::_ix >, ID < IX >, Type < int > >,
-//                     Variable < Name < AModel::_bx >, ID < BX >, Type < bool > >,
-//                     Variable < Name < AModel::_dx >, ID < DX >, Type < double > >
-//                     >,
-//                 Externals < >,
-//                 >,
-//             AtomicModel <
-//                 Type < BModel >,
-//                 Name < RootModel::_b >,
-//                 ID < B >,
-//                 States < >,
-//                 Internals < >,
-//                 Externals < >,
-//                 >
-//             >
-//         >
-//     > ABuilder;
-
 //TEST_CASE("Simulator_tests", "simple")
 int main()
 {
     GlobalParameters globalParameters;
     ModelParameters modelParameters;
-    // ABuilder builder;
-
-    // ABuilder builder("{ \"type\": \"RootModel\", "                   \
-    //                  "\"name\": \"root\", "                          \
-    //                  "\"states\": [ "                                \
-    //                  "{ \"name\":\"_i\", \"type\":\"int\"} "         \
-    //                  "],"                                            \
-    //                  "\"submodels\": [ "                             \
-    //                  "{ \"type\": \"AModel\", "                      \
-    //                  "\"name\": \"_a\", "                            \
-    //                  "\"internals\": ["                              \
-    //                  "{ \"name\":\"_ix\", \"type\":\"int\"}, "       \
-    //                  "{ \"name\":\"_bx\", \"type\":\"bool\"}, "      \
-    //                  "{ \"name\":\"_dx\", \"type\":\"double\"} "     \
-    //                  "] }, "                                         \
-    //                  "{ \"type\": \"BModel\", "                      \
-    //                  "\"name\": \"_b\", "                            \
-    //                  "\"internals\": ["                              \
-    //                  "{ \"name\":\"_iy\", \"type\":\"int\"}, "       \
-    //                  "{ \"name\":\"_by\", \"type\":\"bool\"}, "      \
-    //                  "{ \"name\":\"_dy\", \"type\":\"double\"} "     \
-    //                  "], "                                           \
-    //                  "\"externals\": ["                              \
-    //                  "{ \"name\":\"_ix\", \"type\":\"int\"}, "       \
-    //                  "{ \"name\":\"_bx\", \"type\":\"bool\"}, "      \
-    //                  "{ \"name\":\"_dx\", \"type\":\"double\"} "     \
-    //                  "], "                                           \
-    //                  "\"states\": [ "                                \
-    //                  "{ \"name\":\"_n\", \"type\":\"int\"} "         \
-    //                  "] }"                                           \
-    //                  "] }");
-    // ASimulator simulator(builder(), globalParameters);
-
-    // simulator.attachView("Root", new AView);
-
-    // ::Trace::trace().clear();
-
-    // simulator.init(0, modelParameters);
-    // simulator.run(artis::utils::DateTime::toJulianDayNumber(2016, 1, 1),
-    //               artis::utils::DateTime::toJulianDayNumber(2016, 1, 10));
-
-    // AnOutput output(simulator.observer());
 
-    // output();
+    ABuilder builder("{ \"type\": \"RootModel\", "                   \
+                     "\"name\": \"root\", "                          \
+                     "\"states\": [ "                                \
+                     "{ \"name\":\"_i\", \"type\":\"int\"} "         \
+                     "],"                                            \
+                     "\"submodels\": [ "                             \
+                     "{ \"type\": \"AModel\", "                      \
+                     "\"name\": \"_a\", "                            \
+                     "\"internals\": ["                              \
+                     "{ \"name\":\"_ix\", \"type\":\"int\"}, "       \
+                     "{ \"name\":\"_bx\", \"type\":\"bool\"}, "      \
+                     "{ \"name\":\"_dx\", \"type\":\"double\"} "     \
+                     "] }, "                                         \
+                     "{ \"type\": \"BModel\", "                      \
+                     "\"name\": \"_b\", "                            \
+                     "\"internals\": ["                              \
+                     "{ \"name\":\"_iy\", \"type\":\"int\"}, "       \
+                     "{ \"name\":\"_by\", \"type\":\"bool\"}, "      \
+                     "{ \"name\":\"_dy\", \"type\":\"double\"} "     \
+                     "], "                                           \
+                     "\"externals\": ["                              \
+                     "{ \"name\":\"_ix\", \"type\":\"int\"}, "       \
+                     "{ \"name\":\"_bx\", \"type\":\"bool\"}, "      \
+                     "{ \"name\":\"_dx\", \"type\":\"double\"} "     \
+                     "], "                                           \
+                     "\"states\": [ "                                \
+                     "{ \"name\":\"_n\", \"type\":\"int\"} "         \
+                     "] }"                                           \
+                     "] }");
+
+    ASimulator simulator(builder.build(), globalParameters);
+
+    simulator.attachView("Root", new AView);
+
+    ::Trace::trace().clear();
+
+    simulator.init(0, modelParameters);
+    simulator.run(artis::utils::DateTime::toJulianDayNumber("2016-1-1"),
+                  artis::utils::DateTime::toJulianDayNumber("2016-1-10"));
+
+    AnOutput output(simulator.observer());
+
+    output();
     return 0;
 }

+ 148 - 0
src/test/test2.cpp

@@ -0,0 +1,148 @@
+/**
+ * @file test/test2.cpp
+ * @author See the AUTHORS file
+ */
+
+/*
+ * Copyright (C) 2012-2017 ULCO http://www.univ-littoral.fr
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+//#define CATCH_CONFIG_MAIN
+//#include <test/catch.hpp>
+
+#include <test/models.hpp>
+
+#include <artis/kernel/Simulator.hpp>
+#include <artis/observer/Output.hpp>
+
+#include <artis/utils/DateTime.hpp>
+
+using namespace artis::kernel;
+
+/*
+typedef Builder <
+    CoupledModel <
+        Type < RootModel >,
+        Name < >,
+        ID < >,
+        States < >,
+        Internals < >,
+        Externals < >,
+        Submodels <
+            AtomicModel <
+                Type < AModel >,
+                Name < RootModel::_a >,
+                ID < A >,
+                States < >,
+                Internals <
+                    Variable < Name < AModel::_ix >,
+                               ID < IX >,
+                               Type < int >
+                               >,
+                    Variable < Name < AModel::_bx >,
+                               ID < BX >,
+                               Type < bool >
+                               >,
+                    Variable < Name < AModel::_dx >,
+                               ID < DX >,
+                               Type < double >
+                               >
+                    >,
+                Externals < >,
+                >,
+            AtomicModel <
+                Type < BModel >,
+                Name < RootModel::_b >,
+                ID < B >,
+                States < >,
+                Internals < >,
+                Externals < >,
+                >
+            >
+        >
+    > ABuilder;
+*/
+
+template < class M >
+class mpBuilder
+{
+public:
+    mpBuilder(const std::map < int, int> m)
+    { }
+};
+
+template < class T, class I, class S, class In >
+class mpAtomicModel
+{
+};
+
+template < class M >
+class mpType
+{
+};
+
+template < class M >
+class mpName
+{
+};
+
+template < int N >
+class mpID
+{
+};
+
+template < class... M >
+class mpStates
+{
+};
+
+template < class... M >
+class mpInternals
+{
+};
+
+template < class I, class T >
+class mpVariable
+{
+};
+
+typedef mpBuilder <
+    mpAtomicModel <
+        mpType < AModel >,
+        mpID < RootModel::A >,
+        mpStates < >,
+        mpInternals <
+            mpVariable < mpID < AModel::IX >,
+                         mpType < int >
+                         >,
+            mpVariable < mpID < AModel::BX >,
+                         mpType < bool >
+                         >,
+            mpVariable < mpID < AModel::DX >,
+                         mpType < double >
+                         >
+            >
+        >
+    > ABuilder;
+
+int main()
+{
+    GlobalParameters globalParameters;
+    ModelParameters modelParameters;
+    ABuilder builder({{AModel::IX,1},{AModel::BX,1},{AModel::DX,1}});
+
+    return 0;
+}