Skip to content

Commit

Permalink
Add ParseTime (strptime) native (#1697)
Browse files Browse the repository at this point in the history
* Add GetTimeStamp (strptime) native

* Fix description

* Fix typos

* Fix issues

* Rewrite ParseTime

* Fix docstrings

* Fix ParseTime

* Clarify docs
  • Loading branch information
sirdigbot authored Jul 4, 2023
1 parent f40ae82 commit 5addaff
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
46 changes: 46 additions & 0 deletions core/logic/smn_core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <list>
#include "common_logic.h"
#include "Logger.h"
Expand Down Expand Up @@ -273,6 +275,49 @@ static cell_t FormatTime(IPluginContext *pContext, const cell_t *params)
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)
{
IPluginIterator *iter = scripts->GetPluginIterator();
Expand Down Expand Up @@ -1088,6 +1133,7 @@ REGISTER_NATIVES(coreNatives)
{"ThrowError", ThrowError},
{"GetTime", GetTime},
{"FormatTime", FormatTime},
{"ParseTime", ParseTime},
{"GetPluginIterator", GetPluginIterator},
{"MorePlugins", MorePlugins},
{"ReadPlugin", ReadPlugin},
Expand Down
18 changes: 18 additions & 0 deletions plugins/include/sourcemod.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/**
* 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.
*
Expand Down

0 comments on commit 5addaff

Please sign in to comment.