-
-
Notifications
You must be signed in to change notification settings - Fork 429
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ParseTime (strptime) native #1697
Add ParseTime (strptime) native #1697
Conversation
if my code sucks let me know because boy howdy do i not know what I am doing |
Is this able to be implemented in pawn? I'm not sure we need pure 32bit math in a native (I may have missed the call to a stdio function). |
Not easily. The core of it is |
Ok so Because I had forgotten that I also fixed the locale being changed, a concern that headline had brought up that I didn't really understand at the time. I've tested the new code on Godbolt/GCC and in Visual Studio with: #include <time.h>
#include <iomanip>
#include <sstream>
#include <iostream>
#define PLATFORM_WINDOWS
//static int ParseTime(IPluginContext* pContext, const cell_t* params)
static int ParseTime(const char* datetime, const char* format)
{
//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.");
return -1;
}
std::cout << "std::get_time data:\n"
<< "\ttm_sec:" << t.tm_sec // seconds after the minute - [0, 60] including leap second
<< "\n\ttm_min:" << t.tm_min // minutes after the hour - [0, 59]
<< "\n\ttm_hour:" << t.tm_hour // hours since midnight - [0, 23]
<< "\n\ttm_mday:" << t.tm_mday // day of the month - [1, 31]
<< "\n\ttm_mon:" << t.tm_mon // months since January - [0, 11]
<< "\n\ttm_year:" << t.tm_year // years since 1900
<< "\n\ttm_wday:" << t.tm_wday // days since Sunday - [0, 6]
<< "\n\ttm_yday:" << t.tm_yday // days since January 1 - [0, 365]
<< "\n\ttm_isdst:" << t.tm_isdst // daylight savings time flag
<< std::endl;
#if defined PLATFORM_WINDOWS
return _mkgmtime(&t);
#elif defined PLATFORM_LINUX || defined PLATFORM_APPLE
return timegm(&t);
#else
//return pContext->ThrowNativeError("Platform has no supported UTC conversion for std::tm to std::time_t");
return -1;
#endif
}
int main()
{
char buffer[32];
int utc;
struct tm* ptm;
// Format current time into a string
time_t currentTime = time(NULL);
ptm = gmtime(¤tTime);
strftime(buffer, sizeof buffer, "%Y-%m-%d %H:%M:%S", ptm);
// Get current time from formatted string
utc = ParseTime(buffer, "%Y-%m-%d %H:%M:%S");
std::cout << "ParseTime(): " << utc << "\ntime(): " << currentTime << std::endl;
} And tested it in sourcemod on windows with public void OnPluginStart()
{
// FormatTime uses localtime, we need UTC.
// 1600000000 unix time = Sunday, September 13, 2020 12:26:40 PM
int parsedNow = ParseTime("2020-09-13 12:26:40", "%Y-%m-%d %H:%M:%S");
PrintToServer("UTC: 1600000000\nParseTime: %i", parsedNow);
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested on hl2sdk-mock and it appears to work fine. Thank you and sorry for the delay!
It might be useful to make the timezone explicit since it might not be obvious that unix timestamps are always UTC?
I'm assuming you mean in the docstring? Would adding an offset parameter make sense since too, since presumably you're more likely to have a non-UTC datetime string (given that |
Yes, I was talking about the documentation. I'd rather allow control over the output of FormatTime than including an offset here. |
I realised that actually you could just offset the result of ParseTime for the same effect anyway |
After discussing in the discord I was told this was a sane idea.
Although unfortunately
strptime
is not in MSVCRT, so I had to look around for a cross platform workaround (which works, as far as I am able to understand the explanation)To get it working, I had to include
sstream
andiomanip
intosmn_core.cpp
. I'm not sure if that's some sort of faux pas or not.I also grabbed most of the important logic from SO and another site, so I'm not sure of whether or not this can be merged legitimately.
I tested outside of SM with slightly modified code below: