Add ParseTime (strptime) native (#1697)

* Add GetTimeStamp (strptime) native

* Fix description

* Fix typos

* Fix issues

* Rewrite ParseTime

* Fix docstrings

* Fix ParseTime

* Clarify docs
This commit is contained in:
Corey D 2023-07-04 21:42:45 +10:00 committed by GitHub
parent f40ae82df4
commit 5addaffa56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 64 additions and 0 deletions

View File

@ -32,6 +32,8 @@
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <list> #include <list>
#include "common_logic.h" #include "common_logic.h"
#include "Logger.h" #include "Logger.h"
@ -273,6 +275,49 @@ static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
return 1; return 1;
} }
static int ParseTime(IPluginContext *pContext, const cell_t *params)
{
char *datetime;
char *format;
pContext->LocalToStringNULL(params[1], &datetime);
pContext->LocalToStringNULL(params[2], &format);
if (format == NULL)
{
format = const_cast<char *>(bridge->GetCvarString(g_datetime_format));
}
else if (!format[0])
{
return pContext->ThrowNativeError("Time format string cannot be empty.");
}
if (!datetime || !datetime[0])
{
return pContext->ThrowNativeError("Date/time string cannot be empty.");
}
// https://stackoverflow.com/a/33542189
std::tm t{};
std::istringstream input(datetime);
auto previousLocale = input.imbue(std::locale::classic());
input >> std::get_time(&t, format);
bool failed = input.fail();
input.imbue(previousLocale);
if (failed)
{
return pContext->ThrowNativeError("Invalid date/time string or time format.");
}
#if defined PLATFORM_WINDOWS
return _mkgmtime(&t);
#elif defined PLATFORM_LINUX || defined PLATFORM_APPLE
return timegm(&t);
#else
return pContext->ThrowNativeError("Platform has no implemented UTC conversion for std::tm to std::time_t");
#endif
}
static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params) static cell_t GetPluginIterator(IPluginContext *pContext, const cell_t *params)
{ {
IPluginIterator *iter = scripts->GetPluginIterator(); IPluginIterator *iter = scripts->GetPluginIterator();
@ -1088,6 +1133,7 @@ REGISTER_NATIVES(coreNatives)
{"ThrowError", ThrowError}, {"ThrowError", ThrowError},
{"GetTime", GetTime}, {"GetTime", GetTime},
{"FormatTime", FormatTime}, {"FormatTime", FormatTime},
{"ParseTime", ParseTime},
{"GetPluginIterator", GetPluginIterator}, {"GetPluginIterator", GetPluginIterator},
{"MorePlugins", MorePlugins}, {"MorePlugins", MorePlugins},
{"ReadPlugin", ReadPlugin}, {"ReadPlugin", ReadPlugin},

View File

@ -412,6 +412,24 @@ native int GetTime(int bigStamp[2]={0,0});
*/ */
native void FormatTime(char[] buffer, int maxlength, const char[] format, int stamp=-1); native void FormatTime(char[] buffer, int maxlength, const char[] format, int stamp=-1);
/**
* Parses a string representing a date and/or time into a unix timestamp.
* The timezone is always interpreted as UTC/GMT.
*
* See this URL for valid parameters:
* https://en.cppreference.com/w/cpp/io/manip/get_time
*
* Note that available parameters depends on support from your operating system.
* In particular, ones highlighted in yellow on that page are not currently
* available on Windows and should be avoided for portable plugins.
*
* @param dateTime Date and/or time string.
* @param format Formatting rules (passing NULL_STRING will use the rules defined in sm_datetime_format).
* @return 32bit timestamp (number of seconds since unix epoch).
* @error Invalid date/time string or time format.
*/
native int ParseTime(const char[] dateTime, const char[] format);
/** /**
* Loads a game config file. * Loads a game config file.
* *