diff options
-rw-r--r-- | doc/script_commands.txt | 24 | ||||
-rw-r--r-- | src/map/date.c | 7 | ||||
-rw-r--r-- | src/map/date.h | 1 | ||||
-rw-r--r-- | src/map/script.c | 96 |
4 files changed, 128 insertions, 0 deletions
diff --git a/doc/script_commands.txt b/doc/script_commands.txt index 310af13cc..9148e023c 100644 --- a/doc/script_commands.txt +++ b/doc/script_commands.txt @@ -3408,6 +3408,30 @@ Example : --------------------------------------- +*getcalendartime(<hour>, <minute>{, <day of month>{, <day of week>}}) + +This function returns the timestamp of the next ocurrence of given time. + +Day of Month specifies a day between 1 and 31 in the future, by default its value is -1 (don't use). +Day of Week specifies a day in the week and its valid values are: + 0 - SUNDAY + 1 - MONDAY + 2 - TUESDAY + 3 - WEDNESDAY + 4 - THURSDAY + 5 - FRIDAY + 6 - SATURDAY + +In order to use Day of Week, you must use Day of Month as -1. +If for some reason the command fails, it'll return -1. + +Examples : + getcalendartime(19, 00); // Next 7 pm + getcalendartime(19, 00, 6); // Next day 6 of the month, at 7pm + getcalendartime(19, 10, -1, 1); // Next Monday, at 7:10pm + +--------------------------------------- + *gettimestr(<format string>, <max length>) This function will return a string containing time data as specified by diff --git a/src/map/date.c b/src/map/date.c index a20578e51..20ab9fe95 100644 --- a/src/map/date.c +++ b/src/map/date.c @@ -77,6 +77,13 @@ int date_get_sec(void) return lt->tm_sec; } +int date_get_dayofweek(void) +{ + time_t t = time(NULL); + struct tm *lt = localtime(&t); + return lt->tm_wday; +} + /*========================================== * Star gladiator related checks *------------------------------------------*/ diff --git a/src/map/date.h b/src/map/date.h index 3a109d1ad..ac0a3a7fa 100644 --- a/src/map/date.h +++ b/src/map/date.h @@ -31,6 +31,7 @@ int date_get_day(void); int date_get_hour(void); int date_get_min(void); int date_get_sec(void); +int date_get_dayofweek(void); bool is_day_of_sun(void); bool is_day_of_moon(void); diff --git a/src/map/script.c b/src/map/script.c index 85480d3bd..bef3dc13a 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -30,6 +30,7 @@ #include "map/chat.h" #include "map/chrif.h" #include "map/clif.h" +#include "map/date.h" #include "map/elemental.h" #include "map/guild.h" #include "map/homunculus.h" @@ -23211,6 +23212,100 @@ BUILDIN(mergeitem) return true; } +// getcalendartime(<day of month>, <day of week>{, <hour>{, <minute>}}); +// Returns the UNIX Timestamp of next ocurrency of given time +BUILDIN(getcalendartime) +{ + struct tm info = { 0 }; + int day_of_month = script_hasdata(st, 4) ? script_getnum(st, 4) : -1; + int day_of_week = script_hasdata(st, 5) ? script_getnum(st, 5) : -1; + int year = date_get_year(); + int month = date_get_month(); + int day = date_get_day(); + int cur_hour = date_get_hour(); + int cur_min = date_get_min(); + int hour = script_getnum(st, 2); + int minute = script_getnum(st, 3); + + info.tm_sec = 0; + info.tm_min = minute; + info.tm_hour = hour; + info.tm_mday = day; + info.tm_mon = month - 1; + info.tm_year = year - 1900; + + if (day_of_month > -1 && day_of_week > -1) { + ShowError("script:getcalendartime: You must only specify a day_of_week or a day_of_month, not both\n"); + script_pushint(st, -1); + return false; + } + if (day_of_month > -1 && (day_of_month < 1 || day_of_month > 31)) { + ShowError("script:getcalendartime: Day of Month in invalid range. Must be between 1 and 31.\n"); + script_pushint(st, -1); + return false; + } + if (day_of_week > -1 && (day_of_week < 0 || day_of_week > 6)) { + ShowError("script:getcalendartime: Day of Week in invalid range. Must be between 0 and 6.\n"); + script_pushint(st, -1); + return false; + } + if (hour > -1 && (hour > 23)) { + ShowError("script:getcalendartime: Hour in invalid range. Must be between 0 and 23.\n"); + script_pushint(st, -1); + return false; + } + if (minute > -1 && (minute > 59)) { + ShowError("script:getcalendartime: Minute in invalid range. Must be between 0 and 59.\n"); + script_pushint(st, -1); + return false; + } + if (hour == -1 || minute == -1) { + ShowError("script:getcalendartime: Minutes and Hours are required\n"); + script_pushint(st, -1); + return false; + } + + if (day_of_month > -1) { + if (day_of_month < day) { // Next Month + info.tm_mon++; + } else if (day_of_month == day) { // Today + if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) { // But past time, next month + info.tm_mon++; + } + } + + // Loops until month has finding a month that has day_of_month + do { + time_t t; + struct tm *lt; + info.tm_mday = day_of_month; + t = mktime(&info); + lt = localtime(&t); + info = *lt; + } while (info.tm_mday != day_of_month); + } else if (day_of_week > -1) { + int cur_wday = date_get_dayofweek(); + + if (day_of_week > cur_wday) { // This week + info.tm_mday += (day_of_week - cur_wday); + } else if (day_of_week == cur_wday) { // Today + if (hour < cur_hour || (hour == cur_hour && minute <= cur_min)) { + info.tm_mday += 7; // Next week + } + } else if (day_of_week < cur_wday) { // Next week + info.tm_mday += (7 - cur_wday + day_of_week); + } + } else if (day_of_week == -1 && day_of_month == -1) { // Next occurence of hour/min + if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) { + info.tm_mday++; + } + } + + script_pushint(st, mktime(&info)); + + return true; +} + /** place holder for the translation macro **/ BUILDIN(_) { @@ -23972,6 +24067,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(removechannelhandler, "ss"), BUILDIN_DEF(showscript, "s?"), BUILDIN_DEF(mergeitem,""), + BUILDIN_DEF(getcalendartime, "ii??"), BUILDIN_DEF(_,"s"), BUILDIN_DEF2(_, "_$", "s"), }; |