forked from ground/ground
422 lines
21 KiB
C
422 lines
21 KiB
C
|
|
#include "date_functions.h"
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
GroundValue tmToGroundValue(struct tm t) {
|
||
|
|
GroundStruct timeStruct = groundCreateStruct();
|
||
|
|
groundAddFieldToStruct(&timeStruct, "year", groundCreateValue(INT, t.tm_year + 1900));
|
||
|
|
groundAddFieldToStruct(&timeStruct, "month", groundCreateValue(INT, t.tm_mon + 1));
|
||
|
|
groundAddFieldToStruct(&timeStruct, "day", groundCreateValue(INT, t.tm_mday));
|
||
|
|
groundAddFieldToStruct(&timeStruct, "hour", groundCreateValue(INT, t.tm_hour));
|
||
|
|
groundAddFieldToStruct(&timeStruct, "minute", groundCreateValue(INT, t.tm_min));
|
||
|
|
groundAddFieldToStruct(&timeStruct, "second", groundCreateValue(INT, t.tm_sec));
|
||
|
|
groundAddFieldToStruct(&timeStruct, "weekDay", groundCreateValue(INT, t.tm_wday));
|
||
|
|
groundAddFieldToStruct(&timeStruct, "yearDay", groundCreateValue(INT, t.tm_yday + 1));
|
||
|
|
groundAddFieldToStruct(&timeStruct, "isDaylightSavingsTime", groundCreateValue(BOOL, t.tm_isdst));
|
||
|
|
|
||
|
|
GroundValue value = groundCreateValue(CUSTOM, &timeStruct);
|
||
|
|
value.type = CUSTOM;
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_Now(GroundScope* scope, List args) {
|
||
|
|
time_t now = time(NULL);
|
||
|
|
struct tm t = {0};
|
||
|
|
|
||
|
|
localtime_r(&now, &t);
|
||
|
|
|
||
|
|
// return a -datetime struct
|
||
|
|
return tmToGroundValue(t);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_FromEpochLocal(GroundScope* scope, List args) {
|
||
|
|
struct tm t = {0};
|
||
|
|
time_t ts = args.values[0].data.doubleVal;
|
||
|
|
|
||
|
|
localtime_r(&ts, &t);
|
||
|
|
|
||
|
|
return tmToGroundValue(t);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_FromEpochUTC(GroundScope* scope, List args) {
|
||
|
|
struct tm t = {0};
|
||
|
|
time_t ts = args.values[0].data.doubleVal;
|
||
|
|
|
||
|
|
gmtime_r(&ts, &t);
|
||
|
|
|
||
|
|
return tmToGroundValue(t);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_ToEpochLocal(GroundScope* scope, List args) {
|
||
|
|
GroundObject obj = *args.values[0].data.customVal;
|
||
|
|
|
||
|
|
// check args
|
||
|
|
GroundObjectField* year = groundFindField(obj, "year");
|
||
|
|
if (year == NULL || year->value.type != INT) ERROR("Object does not have year field as int", "ValueError");
|
||
|
|
GroundObjectField* month = groundFindField(obj, "month");
|
||
|
|
if (month == NULL || month->value.type != INT) ERROR("Object does not have month field as int", "ValueError");
|
||
|
|
GroundObjectField* day = groundFindField(obj, "day");
|
||
|
|
if (day == NULL || day->value.type != INT) ERROR("Object does not have day field as int", "ValueError");
|
||
|
|
GroundObjectField* hour = groundFindField(obj, "hour");
|
||
|
|
if (hour == NULL || hour->value.type != INT) ERROR("Object does not have hour field as int", "ValueError");
|
||
|
|
GroundObjectField* minute = groundFindField(obj, "minute");
|
||
|
|
if (minute == NULL || minute->value.type != INT) ERROR("Object does not have minute field as int", "ValueError");
|
||
|
|
GroundObjectField* second = groundFindField(obj, "second");
|
||
|
|
if (second == NULL || second->value.type != INT) ERROR("Object does not have second field as int", "ValueError");
|
||
|
|
GroundObjectField* weekDay = groundFindField(obj, "weekDay");
|
||
|
|
if (weekDay == NULL || weekDay->value.type != INT) ERROR("Object does not have weekDay field as int", "ValueError");
|
||
|
|
GroundObjectField* yearDay = groundFindField(obj, "yearDay");
|
||
|
|
if (yearDay == NULL || yearDay->value.type != INT) ERROR("Object does not have yearDay field as int", "ValueError");
|
||
|
|
GroundObjectField* isDaylightSavingsTime = groundFindField(obj, "isDaylightSavingsTime");
|
||
|
|
if (isDaylightSavingsTime == NULL || isDaylightSavingsTime->value.type != BOOL) ERROR("Object does not have isDaylightSavingsTime field as bool", "ValueError");
|
||
|
|
|
||
|
|
// construct tm struct from our ground struct
|
||
|
|
struct tm t = {
|
||
|
|
.tm_sec = second->value.data.intVal,
|
||
|
|
.tm_min = minute->value.data.intVal,
|
||
|
|
.tm_hour = hour->value.data.intVal,
|
||
|
|
.tm_mday = day->value.data.intVal,
|
||
|
|
.tm_mon = month->value.data.intVal - 1,
|
||
|
|
.tm_year = year->value.data.intVal - 1900,
|
||
|
|
.tm_wday = 0,
|
||
|
|
.tm_yday = 0,
|
||
|
|
.tm_isdst = -1
|
||
|
|
};
|
||
|
|
|
||
|
|
time_t ts = mktime(&t);
|
||
|
|
return groundCreateValue(DOUBLE, (double)ts);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_ToEpochUTC(GroundScope* scope, List args) {
|
||
|
|
GroundObject obj = *args.values[0].data.customVal;
|
||
|
|
|
||
|
|
// check args
|
||
|
|
GroundObjectField* year = groundFindField(obj, "year");
|
||
|
|
if (year == NULL || year->value.type != INT) ERROR("Object does not have year field as int", "ValueError");
|
||
|
|
GroundObjectField* month = groundFindField(obj, "month");
|
||
|
|
if (month == NULL || month->value.type != INT) ERROR("Object does not have month field as int", "ValueError");
|
||
|
|
GroundObjectField* day = groundFindField(obj, "day");
|
||
|
|
if (day == NULL || day->value.type != INT) ERROR("Object does not have day field as int", "ValueError");
|
||
|
|
GroundObjectField* hour = groundFindField(obj, "hour");
|
||
|
|
if (hour == NULL || hour->value.type != INT) ERROR("Object does not have hour field as int", "ValueError");
|
||
|
|
GroundObjectField* minute = groundFindField(obj, "minute");
|
||
|
|
if (minute == NULL || minute->value.type != INT) ERROR("Object does not have minute field as int", "ValueError");
|
||
|
|
GroundObjectField* second = groundFindField(obj, "second");
|
||
|
|
if (second == NULL || second->value.type != INT) ERROR("Object does not have second field as int", "ValueError");
|
||
|
|
GroundObjectField* weekDay = groundFindField(obj, "weekDay");
|
||
|
|
if (weekDay == NULL || weekDay->value.type != INT) ERROR("Object does not have weekDay field as int", "ValueError");
|
||
|
|
GroundObjectField* yearDay = groundFindField(obj, "yearDay");
|
||
|
|
if (yearDay == NULL || yearDay->value.type != INT) ERROR("Object does not have yearDay field as int", "ValueError");
|
||
|
|
GroundObjectField* isDaylightSavingsTime = groundFindField(obj, "isDaylightSavingsTime");
|
||
|
|
if (isDaylightSavingsTime == NULL || isDaylightSavingsTime->value.type != BOOL) ERROR("Object does not have isDaylightSavingsTime field as bool", "ValueError");
|
||
|
|
|
||
|
|
// construct tm struct from our ground struct
|
||
|
|
struct tm t = {
|
||
|
|
.tm_sec = second->value.data.intVal,
|
||
|
|
.tm_min = minute->value.data.intVal,
|
||
|
|
.tm_hour = hour->value.data.intVal,
|
||
|
|
.tm_mday = day->value.data.intVal,
|
||
|
|
.tm_mon = month->value.data.intVal - 1,
|
||
|
|
.tm_year = year->value.data.intVal - 1900,
|
||
|
|
.tm_wday = 0,
|
||
|
|
.tm_yday = 0,
|
||
|
|
.tm_isdst = -1
|
||
|
|
};
|
||
|
|
|
||
|
|
time_t ts = timegm(&t);
|
||
|
|
return groundCreateValue(DOUBLE, (double)ts);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue formatDatetimeObj(GroundObject obj, char* formatString) {
|
||
|
|
// check args
|
||
|
|
GroundObjectField* year = groundFindField(obj, "year");
|
||
|
|
if (year == NULL || year->value.type != INT) ERROR("Object does not have year field as int", "ValueError");
|
||
|
|
GroundObjectField* month = groundFindField(obj, "month");
|
||
|
|
if (month == NULL || month->value.type != INT) ERROR("Object does not have month field as int", "ValueError");
|
||
|
|
GroundObjectField* day = groundFindField(obj, "day");
|
||
|
|
if (day == NULL || day->value.type != INT) ERROR("Object does not have day field as int", "ValueError");
|
||
|
|
GroundObjectField* hour = groundFindField(obj, "hour");
|
||
|
|
if (hour == NULL || hour->value.type != INT) ERROR("Object does not have hour field as int", "ValueError");
|
||
|
|
GroundObjectField* minute = groundFindField(obj, "minute");
|
||
|
|
if (minute == NULL || minute->value.type != INT) ERROR("Object does not have minute field as int", "ValueError");
|
||
|
|
GroundObjectField* second = groundFindField(obj, "second");
|
||
|
|
if (second == NULL || second->value.type != INT) ERROR("Object does not have second field as int", "ValueError");
|
||
|
|
GroundObjectField* weekDay = groundFindField(obj, "weekDay");
|
||
|
|
if (weekDay == NULL || weekDay->value.type != INT) ERROR("Object does not have weekDay field as int", "ValueError");
|
||
|
|
GroundObjectField* yearDay = groundFindField(obj, "yearDay");
|
||
|
|
if (yearDay == NULL || yearDay->value.type != INT) ERROR("Object does not have yearDay field as int", "ValueError");
|
||
|
|
GroundObjectField* isDaylightSavingsTime = groundFindField(obj, "isDaylightSavingsTime");
|
||
|
|
if (isDaylightSavingsTime == NULL || isDaylightSavingsTime->value.type != BOOL) ERROR("Object does not have isDaylightSavingsTime field as bool", "ValueError");
|
||
|
|
|
||
|
|
// construct tm struct from our ground struct
|
||
|
|
struct tm t = {
|
||
|
|
.tm_sec = second->value.data.intVal,
|
||
|
|
.tm_min = minute->value.data.intVal,
|
||
|
|
.tm_hour = hour->value.data.intVal,
|
||
|
|
.tm_mday = day->value.data.intVal,
|
||
|
|
.tm_mon = month->value.data.intVal - 1,
|
||
|
|
.tm_year = year->value.data.intVal - 1900,
|
||
|
|
.tm_wday = 0,
|
||
|
|
.tm_yday = 0,
|
||
|
|
.tm_isdst = -1
|
||
|
|
};
|
||
|
|
|
||
|
|
mktime(&t); // normalise time
|
||
|
|
|
||
|
|
// create a buffer for the string
|
||
|
|
char* buffer = (char*)malloc(128);
|
||
|
|
strftime(buffer, 128, formatString, &t);
|
||
|
|
|
||
|
|
// return ground version of string
|
||
|
|
return groundCreateValue(STRING, buffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_Format(GroundScope* scope, List args) {
|
||
|
|
return formatDatetimeObj(
|
||
|
|
*args.values[0].data.customVal,
|
||
|
|
args.values[1].data.stringVal
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_FromFormatted(GroundScope* scope, List args) {
|
||
|
|
char* timeString = args.values[0].data.stringVal;
|
||
|
|
char* formatString = args.values[1].data.stringVal;
|
||
|
|
|
||
|
|
struct tm t = {0};
|
||
|
|
t.tm_isdst = -1;
|
||
|
|
char* result = strptime(timeString, formatString, &t);
|
||
|
|
|
||
|
|
if (result == NULL) {
|
||
|
|
ERROR("Time string does not match format!", "ValueError");
|
||
|
|
}
|
||
|
|
|
||
|
|
mktime(&t);
|
||
|
|
|
||
|
|
return tmToGroundValue(t);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_ToISO8601UTC(GroundScope* scope, List args) {
|
||
|
|
GroundObject obj = *args.values[0].data.customVal;
|
||
|
|
|
||
|
|
// check args
|
||
|
|
GroundObjectField* year = groundFindField(obj, "year");
|
||
|
|
if (year == NULL || year->value.type != INT) ERROR("Object does not have year field as int", "ValueError");
|
||
|
|
GroundObjectField* month = groundFindField(obj, "month");
|
||
|
|
if (month == NULL || month->value.type != INT) ERROR("Object does not have month field as int", "ValueError");
|
||
|
|
GroundObjectField* day = groundFindField(obj, "day");
|
||
|
|
if (day == NULL || day->value.type != INT) ERROR("Object does not have day field as int", "ValueError");
|
||
|
|
GroundObjectField* hour = groundFindField(obj, "hour");
|
||
|
|
if (hour == NULL || hour->value.type != INT) ERROR("Object does not have hour field as int", "ValueError");
|
||
|
|
GroundObjectField* minute = groundFindField(obj, "minute");
|
||
|
|
if (minute == NULL || minute->value.type != INT) ERROR("Object does not have minute field as int", "ValueError");
|
||
|
|
GroundObjectField* second = groundFindField(obj, "second");
|
||
|
|
if (second == NULL || second->value.type != INT) ERROR("Object does not have second field as int", "ValueError");
|
||
|
|
GroundObjectField* weekDay = groundFindField(obj, "weekDay");
|
||
|
|
if (weekDay == NULL || weekDay->value.type != INT) ERROR("Object does not have weekDay field as int", "ValueError");
|
||
|
|
GroundObjectField* yearDay = groundFindField(obj, "yearDay");
|
||
|
|
if (yearDay == NULL || yearDay->value.type != INT) ERROR("Object does not have yearDay field as int", "ValueError");
|
||
|
|
GroundObjectField* isDaylightSavingsTime = groundFindField(obj, "isDaylightSavingsTime");
|
||
|
|
if (isDaylightSavingsTime == NULL || isDaylightSavingsTime->value.type != BOOL) ERROR("Object does not have isDaylightSavingsTime field as bool", "ValueError");
|
||
|
|
|
||
|
|
// construct tm struct from our ground struct
|
||
|
|
struct tm t = {
|
||
|
|
.tm_sec = second->value.data.intVal,
|
||
|
|
.tm_min = minute->value.data.intVal,
|
||
|
|
.tm_hour = hour->value.data.intVal,
|
||
|
|
.tm_mday = day->value.data.intVal,
|
||
|
|
.tm_mon = month->value.data.intVal - 1,
|
||
|
|
.tm_year = year->value.data.intVal - 1900,
|
||
|
|
.tm_wday = 0,
|
||
|
|
.tm_yday = 0,
|
||
|
|
.tm_isdst = -1
|
||
|
|
};
|
||
|
|
|
||
|
|
time_t ts = mktime(&t);
|
||
|
|
gmtime_r(&ts, &t);
|
||
|
|
|
||
|
|
char* buffer = (char*)malloc(128);
|
||
|
|
strftime(buffer, 128, "%Y-%m-%dT%H:%M:%SZ", &t);
|
||
|
|
|
||
|
|
return groundCreateValue(STRING, buffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_ToISO8601Local(GroundScope* scope, List args) {
|
||
|
|
GroundObject obj = *args.values[0].data.customVal;
|
||
|
|
|
||
|
|
// check args
|
||
|
|
GroundObjectField* year = groundFindField(obj, "year");
|
||
|
|
if (year == NULL || year->value.type != INT) ERROR("Object does not have year field as int", "ValueError");
|
||
|
|
GroundObjectField* month = groundFindField(obj, "month");
|
||
|
|
if (month == NULL || month->value.type != INT) ERROR("Object does not have month field as int", "ValueError");
|
||
|
|
GroundObjectField* day = groundFindField(obj, "day");
|
||
|
|
if (day == NULL || day->value.type != INT) ERROR("Object does not have day field as int", "ValueError");
|
||
|
|
GroundObjectField* hour = groundFindField(obj, "hour");
|
||
|
|
if (hour == NULL || hour->value.type != INT) ERROR("Object does not have hour field as int", "ValueError");
|
||
|
|
GroundObjectField* minute = groundFindField(obj, "minute");
|
||
|
|
if (minute == NULL || minute->value.type != INT) ERROR("Object does not have minute field as int", "ValueError");
|
||
|
|
GroundObjectField* second = groundFindField(obj, "second");
|
||
|
|
if (second == NULL || second->value.type != INT) ERROR("Object does not have second field as int", "ValueError");
|
||
|
|
GroundObjectField* weekDay = groundFindField(obj, "weekDay");
|
||
|
|
if (weekDay == NULL || weekDay->value.type != INT) ERROR("Object does not have weekDay field as int", "ValueError");
|
||
|
|
GroundObjectField* yearDay = groundFindField(obj, "yearDay");
|
||
|
|
if (yearDay == NULL || yearDay->value.type != INT) ERROR("Object does not have yearDay field as int", "ValueError");
|
||
|
|
GroundObjectField* isDaylightSavingsTime = groundFindField(obj, "isDaylightSavingsTime");
|
||
|
|
if (isDaylightSavingsTime == NULL || isDaylightSavingsTime->value.type != BOOL) ERROR("Object does not have isDaylightSavingsTime field as bool", "ValueError");
|
||
|
|
|
||
|
|
// construct tm struct from our ground struct
|
||
|
|
struct tm t = {
|
||
|
|
.tm_sec = second->value.data.intVal,
|
||
|
|
.tm_min = minute->value.data.intVal,
|
||
|
|
.tm_hour = hour->value.data.intVal,
|
||
|
|
.tm_mday = day->value.data.intVal,
|
||
|
|
.tm_mon = month->value.data.intVal - 1,
|
||
|
|
.tm_year = year->value.data.intVal - 1900,
|
||
|
|
.tm_wday = 0,
|
||
|
|
.tm_yday = 0,
|
||
|
|
.tm_isdst = -1
|
||
|
|
};
|
||
|
|
|
||
|
|
time_t ts = mktime(&t);
|
||
|
|
localtime_r(&ts, &t);
|
||
|
|
|
||
|
|
char* buffer = (char*)malloc(128);
|
||
|
|
strftime(buffer, 128, "%Y-%m-%dT%H:%M:%S%z", &t);
|
||
|
|
|
||
|
|
return groundCreateValue(STRING, buffer);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_Diff(GroundScope* scope, List args) {
|
||
|
|
GroundObject obj1 = *args.values[0].data.customVal;
|
||
|
|
GroundObject obj2 = *args.values[1].data.customVal;
|
||
|
|
|
||
|
|
// check first timedate object
|
||
|
|
GroundObjectField* year = groundFindField(obj1, "year");
|
||
|
|
if (year == NULL || year->value.type != INT) ERROR("Object 1 does not have year field as int", "ValueError");
|
||
|
|
GroundObjectField* month = groundFindField(obj1, "month");
|
||
|
|
if (month == NULL || month->value.type != INT) ERROR("Object 1 does not have month field as int", "ValueError");
|
||
|
|
GroundObjectField* day = groundFindField(obj1, "day");
|
||
|
|
if (day == NULL || day->value.type != INT) ERROR("Object 1 does not have day field as int", "ValueError");
|
||
|
|
GroundObjectField* hour = groundFindField(obj1, "hour");
|
||
|
|
if (hour == NULL || hour->value.type != INT) ERROR("Object 1 does not have hour field as int", "ValueError");
|
||
|
|
GroundObjectField* minute = groundFindField(obj1, "minute");
|
||
|
|
if (minute == NULL || minute->value.type != INT) ERROR("Object 1 does not have minute field as int", "ValueError");
|
||
|
|
GroundObjectField* second = groundFindField(obj1, "second");
|
||
|
|
if (second == NULL || second->value.type != INT) ERROR("Object 1 does not have second field as int", "ValueError");
|
||
|
|
GroundObjectField* weekDay = groundFindField(obj1, "weekDay");
|
||
|
|
if (weekDay == NULL || weekDay->value.type != INT) ERROR("Object 1 does not have weekDay field as int", "ValueError");
|
||
|
|
GroundObjectField* yearDay = groundFindField(obj1, "yearDay");
|
||
|
|
if (yearDay == NULL || yearDay->value.type != INT) ERROR("Object 1 does not have yearDay field as int", "ValueError");
|
||
|
|
GroundObjectField* isDaylightSavingsTime = groundFindField(obj1, "isDaylightSavingsTime");
|
||
|
|
if (isDaylightSavingsTime == NULL || isDaylightSavingsTime->value.type != BOOL) ERROR("Object 1 does not have isDaylightSavingsTime field as bool", "ValueError");
|
||
|
|
|
||
|
|
// construct tm struct from our ground struct
|
||
|
|
struct tm t1 = {
|
||
|
|
.tm_sec = second->value.data.intVal,
|
||
|
|
.tm_min = minute->value.data.intVal,
|
||
|
|
.tm_hour = hour->value.data.intVal,
|
||
|
|
.tm_mday = day->value.data.intVal,
|
||
|
|
.tm_mon = month->value.data.intVal - 1,
|
||
|
|
.tm_year = year->value.data.intVal - 1900,
|
||
|
|
.tm_wday = 0,
|
||
|
|
.tm_yday = 0,
|
||
|
|
.tm_isdst = -1
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
// check second timedate object
|
||
|
|
year = groundFindField(obj2, "year");
|
||
|
|
if (year == NULL || year->value.type != INT) ERROR("Object does not have year field as int", "ValueError");
|
||
|
|
month = groundFindField(obj2, "month");
|
||
|
|
if (month == NULL || month->value.type != INT) ERROR("Object does not have month field as int", "ValueError");
|
||
|
|
day = groundFindField(obj2, "day");
|
||
|
|
if (day == NULL || day->value.type != INT) ERROR("Object does not have day field as int", "ValueError");
|
||
|
|
hour = groundFindField(obj2, "hour");
|
||
|
|
if (hour == NULL || hour->value.type != INT) ERROR("Object does not have hour field as int", "ValueError");
|
||
|
|
minute = groundFindField(obj2, "minute");
|
||
|
|
if (minute == NULL || minute->value.type != INT) ERROR("Object does not have minute field as int", "ValueError");
|
||
|
|
second = groundFindField(obj2, "second");
|
||
|
|
if (second == NULL || second->value.type != INT) ERROR("Object does not have second field as int", "ValueError");
|
||
|
|
weekDay = groundFindField(obj2, "weekDay");
|
||
|
|
if (weekDay == NULL || weekDay->value.type != INT) ERROR("Object does not have weekDay field as int", "ValueError");
|
||
|
|
yearDay = groundFindField(obj2, "yearDay");
|
||
|
|
if (yearDay == NULL || yearDay->value.type != INT) ERROR("Object does not have yearDay field as int", "ValueError");
|
||
|
|
isDaylightSavingsTime = groundFindField(obj2, "isDaylightSavingsTime");
|
||
|
|
if (isDaylightSavingsTime == NULL || isDaylightSavingsTime->value.type != BOOL) ERROR("Object does not have isDaylightSavingsTime field as bool", "ValueError");
|
||
|
|
|
||
|
|
// construct tm struct from our ground struct
|
||
|
|
struct tm t2 = {
|
||
|
|
.tm_sec = second->value.data.intVal,
|
||
|
|
.tm_min = minute->value.data.intVal,
|
||
|
|
.tm_hour = hour->value.data.intVal,
|
||
|
|
.tm_mday = day->value.data.intVal,
|
||
|
|
.tm_mon = month->value.data.intVal - 1,
|
||
|
|
.tm_year = year->value.data.intVal - 1900,
|
||
|
|
.tm_wday = 0,
|
||
|
|
.tm_yday = 0,
|
||
|
|
.tm_isdst = -1
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
time_t ts1 = mktime(&t1);
|
||
|
|
time_t ts2 = mktime(&t2);
|
||
|
|
|
||
|
|
return groundCreateValue(INT, ts2 - ts1);
|
||
|
|
}
|
||
|
|
|
||
|
|
GroundValue datetime_Add(GroundScope* scope, List args) {
|
||
|
|
GroundObject obj = *args.values[0].data.customVal;
|
||
|
|
|
||
|
|
long long secs = args.values[1].data.intVal;
|
||
|
|
long long mins = args.values[2].data.intVal;
|
||
|
|
long long hours = args.values[3].data.intVal;
|
||
|
|
long long days = args.values[4].data.intVal;
|
||
|
|
|
||
|
|
// check args
|
||
|
|
GroundObjectField* year = groundFindField(obj, "year");
|
||
|
|
if (year == NULL || year->value.type != INT) ERROR("Object does not have year field as int", "ValueError");
|
||
|
|
GroundObjectField* month = groundFindField(obj, "month");
|
||
|
|
if (month == NULL || month->value.type != INT) ERROR("Object does not have month field as int", "ValueError");
|
||
|
|
GroundObjectField* day = groundFindField(obj, "day");
|
||
|
|
if (day == NULL || day->value.type != INT) ERROR("Object does not have day field as int", "ValueError");
|
||
|
|
GroundObjectField* hour = groundFindField(obj, "hour");
|
||
|
|
if (hour == NULL || hour->value.type != INT) ERROR("Object does not have hour field as int", "ValueError");
|
||
|
|
GroundObjectField* minute = groundFindField(obj, "minute");
|
||
|
|
if (minute == NULL || minute->value.type != INT) ERROR("Object does not have minute field as int", "ValueError");
|
||
|
|
GroundObjectField* second = groundFindField(obj, "second");
|
||
|
|
if (second == NULL || second->value.type != INT) ERROR("Object does not have second field as int", "ValueError");
|
||
|
|
GroundObjectField* weekDay = groundFindField(obj, "weekDay");
|
||
|
|
if (weekDay == NULL || weekDay->value.type != INT) ERROR("Object does not have weekDay field as int", "ValueError");
|
||
|
|
GroundObjectField* yearDay = groundFindField(obj, "yearDay");
|
||
|
|
if (yearDay == NULL || yearDay->value.type != INT) ERROR("Object does not have yearDay field as int", "ValueError");
|
||
|
|
GroundObjectField* isDaylightSavingsTime = groundFindField(obj, "isDaylightSavingsTime");
|
||
|
|
if (isDaylightSavingsTime == NULL || isDaylightSavingsTime->value.type != BOOL) ERROR("Object does not have isDaylightSavingsTime field as bool", "ValueError");
|
||
|
|
|
||
|
|
// construct tm struct from our ground struct
|
||
|
|
struct tm t = {
|
||
|
|
.tm_sec = second->value.data.intVal,
|
||
|
|
.tm_min = minute->value.data.intVal,
|
||
|
|
.tm_hour = hour->value.data.intVal,
|
||
|
|
.tm_mday = day->value.data.intVal,
|
||
|
|
.tm_mon = month->value.data.intVal - 1,
|
||
|
|
.tm_year = year->value.data.intVal - 1900,
|
||
|
|
.tm_wday = 0,
|
||
|
|
.tm_yday = 0,
|
||
|
|
.tm_isdst = -1
|
||
|
|
};
|
||
|
|
|
||
|
|
time_t base = mktime(&t);
|
||
|
|
|
||
|
|
long long totalSeconds =
|
||
|
|
secs +
|
||
|
|
mins * 60 +
|
||
|
|
hours * 3600 +
|
||
|
|
days * 86400;
|
||
|
|
|
||
|
|
base += totalSeconds;
|
||
|
|
|
||
|
|
struct tm newT;
|
||
|
|
localtime_r(&base, &newT);
|
||
|
|
|
||
|
|
return tmToGroundValue(newT);
|
||
|
|
|
||
|
|
}
|