Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
Hi,
I need to get the current time and some other time and compare them. Both are possibly in different time zones, so my guess is that using UniversalDateTime and converting to LocalDateTime is the way to go here. I need to find out the difference between currentDate and otherDate in days.
UniversalDateTime
LocalDateTime
currentDate
otherDate
I could not find an example for this.
This is the code so far:
// Get current date maxon::LocalDateTime currentDate(maxon::LocalDateTime::GetNow()); // Format string for date parsing const Char* dateFormatString = "%Y%m%d"; // Some other date String otherDateString = String("20200801"); // For testing, use August 1st 2020 const maxon::LocalDateTime otherDate = maxon::LocalDateTime::FromString(otherDateString, dateFormatString) iferr_ignore(); // How many days between the dates? maxon::UniversalDateTime difference = otherDate.ConvertToUniversalDateTime() - currentDate.ConvertToUniversalDateTime(); // Obviously, not correct
Thanks in advance & cheers, Frank
EDIT: Originally, I had posted two questions. The solution to the first one came to me right after posting, so I removed the question.
Inspired by a posting on Stackoverflow and a page in the SDK docs, I tried it like this:
std::tm stdCurrentDate = maxon::ConvertLocalDateTimeToTM(currentDate); std::tm stdOtherDate = maxon::ConvertLocalDateTimeToTM(otherDate); Int32 daysDifference = (Int32)(std::difftime(std::mktime(&stdOtherDate), std::mktime(&stdCurrentDate)) / (60 * 60 * 24));
But it does not compile, because there is no ConvertLocalDateTimeToTM() in the maxon namespace.
ConvertLocalDateTimeToTM()
maxon
I learned about that function on this documentation page: https://developers.maxon.net/docs/Cinema4DCPPSDK/html/page_maxonapi_maxon_convertlocaldatetimetofromtm.html, which header do I have to include to make it work? It does not seem to be maxon/ansi_type_conversions.h, as that gives me several errors when included.
maxon/ansi_type_conversions.h
By the way, the above posted code also throws a rather strange error:
No member named 'FORBIDDENI_CALL_USE_mktime_r' in namespace 'std' Is it possible that it's supposed to be FORBIDDEN_CALL_USE_mktime_r, without the "I" ?
No member named 'FORBIDDENI_CALL_USE_mktime_r' in namespace 'std'
FORBIDDEN_CALL_USE_mktime_r
Also, the documentation for that macro is a bit confusing (ansi_type_conversions.h, line 122): // The following functions should be avoided. On Windows and OSX these functions are thread-safe, but not on Windows. So, are they thread safe on Windows, or are they not?
ansi_type_conversions.h
// The following functions should be avoided. On Windows and OSX these functions are thread-safe, but not on Windows.
Hm,
I might be overlooking something here, as I just did look at the the docs, but are the arithmetic operators for UniversalDateTime not only defined for TimeValue as being the other operand (Signature for the difference operator), while you are trying to invoke it on another UniversalDateTime?
TimeValue
Have you considered to just subtract the Unix epoch format representation of your values (via UniversalDateTime::GetUnixTimestamp()) and then convert that result into the desired output format (e.g. days) by simple division?
UniversalDateTime::GetUnixTimestamp()
edit: eh, I did overlook the "obviously not correct" comment, due to being on an iPad, but the rest should still apply.
Cheers zipit
That sounds feasible, I'll try that. Thanks!
However, I would still like to know how I can (or why I can't) use ConvertLocalDateTimeToTM(), as it is listed in the SDK docs.
I tried like this:
// Format string for date parsing const Char* dateFormatString = "%Y%m%d"; // Current date maxon::LocalDateTime currentDate(maxon::LocalDateTime::GetNow()); // Get expiry date expirationDateString = String("20191025"); maxon::LocalDateTime expirationDate = maxon::LocalDateTime::FromString(expirationDateString, dateFormatString) iferr_ignore(); expirationDate._hour = 0; expirationDate._minute = 0; expirationDate._second = 0; expirationDate._daylightSavingTime = maxon::DST::AUTOMATIC; // Convert local to universal datetime maxon::UniversalDateTime universalCurrentDate = currentDate.ConvertToUniversalDateTime(); maxon::UniversalDateTime universalExpirationDate = expirationDate.ConvertToUniversalDateTime(); // Convert universal datetime to Unix timestamp UInt64 currentDateStamp = universalCurrentDate.GetUnixTimestamp(); UInt64 expirationDateStamp = universalExpirationDate.GetUnixTimestamp(); // Subtract timestamps UInt64 remainingDaysStamp = expirationDateStamp - currentDateStamp; // Convert seconds to days Int64 daysDifference = remainingDaysStamp / (60 * 60 * 24);
But it gives me an incredibly high value for daysDifference, even though the dates are just 4 days apart.
Printing the values to the console, these are the surprising results:
Current date LOCAL: 2019-10-29 10:51:20 (that is correct!) Expiration date LOCAL: 2019-10-25 00:00:00 (that is what I expected, too) Current date UNIVERSAL: 2019-10-29 09:51:20 (that is also correct) Expiration date UNIVERSAL: 2019-10-24 22:00:00 (why 22:00 ??) Current date UNIX: 1572342680 Expiration date UNIX: 1571954400 Days difference: 213503982334596 (why??)
How cumbersome can it be to just subtract two dates from each other? If I just knew how to use ConvertLocalDateTimeToTM(), the problem would've been long solved.
And why is daysDifference so large? If I calculate it myself with a pocket calculator, I get this:
(1571954400 - 1572342680) / (60 * 60 * 24) = -4,4939814815
And that is exactly why I would expect: About four and a half days.
hm, I am not much into the finer details of C++ (in this case how C++ handles implicit casts like this), but could it be, that the reason is, that the Unix time stamps returned by the date time objects are unsigned integers (which strikes me as an odd choice anyways, since they are also 64 bit) and you implicitly cast them into a signed integer carrying over an integer overflow? So maybe try casting them into signed integers before or just sort out min/max conditions before.
Now that you mention it, I just noticed it, too.
I guess that was my daily dose of shame....
remainingDaysStamp needs to be Int64, not UInt64.
remainingDaysStamp
Thank you so much, that brought me back on track!
Cheers, Frank
jeah, oops, I somehow red remainingDaysStamp as being Int64, mixing it up with daysDifference below. This is a straight up integer overflow. But I am not quite sure if changing remainingDaysStamp will be enough, you might have to convert your operand values to signed integers. At least in older versions of C# the compiler behaved that way (trying to implicitly cast int my_int = smaller_uint - bigger_uint; gave you the overflow value).
Int64
daysDifference
int my_int = smaller_uint - bigger_uint;
I got it working now. Thank you!
Hi Frank, looks like I came too late here
Thanks @zipit and @fwilleke80 for running the conversation. Couple of notes:
Below my suggested version
iferr_scope; // get the current time in UniversalDateTime const maxon::UniversalDateTime currentUDate(maxon::UniversalDateTime::GetNow()); // get the other time in UniversalDateTime const maxon::UniversalDateTime otherUDate = maxon::UniversalDateTime::FromValues(2019, 10, 01, 00, 00, 00) iferr_return; // compute the timestamp difference between the twos UInt64 utDifference = 0; if (currentUDate > otherUDate) utDifference = currentUDate.GetUnixTimestamp() - otherUDate.GetUnixTimestamp(); else utDifference = otherUDate.GetUnixTimestamp() - currentUDate.GetUnixTimestamp(); // allocate some conversion factors const Float toMin = 60; const Float toHour = 60 * toMin; const Float toDay = 24.0 * toHour; // compute the respective temporal differences const UInt days = UInt(utDifference / toDay); const UInt hours = UInt((utDifference - days * toDay) / toHour); const UInt mins = UInt((utDifference - days * toDay - hours * toHour) / toMin); const UInt secs = UInt(utDifference - days * toDay - hours * toHour - mins * toMin); // just print if (currentUDate > otherUDate) DiagnosticOutput("Difference between @ and @ is \n\[email protected] days\n\[email protected] hours\n\[email protected] mins\n\[email protected] secs", currentUDate, otherUDate, days, hours, mins, secs); else DiagnosticOutput("Difference between @ and @ is \n\[email protected] days\n\[email protected] hours\n\[email protected] mins\n\[email protected] secs", otherUDate, currentUDate, days, hours, mins, secs); return maxon::OK;
Cheers, R
Thank you, Ricardo!