Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush Python API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    LocalDateTime, UniversalDateTime... how to compare

    Cinema 4D SDK
    c++ r21 classic api maxon api
    3
    13
    1.3k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ferdinandF
      ferdinand
      last edited by ferdinand

      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?

      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?

      edit: eh, I did overlook the "obviously not correct" comment, due to being on an iPad, but the rest should still apply.

      Cheers
      zipit

      MAXON SDK Specialist
      developers.maxon.net

      1 Reply Last reply Reply Quote 0
      • fwilleke80F
        fwilleke80
        last edited by

        That sounds feasible, I'll try that. Thanks!

        www.frankwilleke.de
        Only asking personal code questions here.

        1 Reply Last reply Reply Quote 0
        • fwilleke80F
          fwilleke80
          last edited by

          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.

          www.frankwilleke.de
          Only asking personal code questions here.

          1 Reply Last reply Reply Quote 0
          • fwilleke80F
            fwilleke80
            last edited by fwilleke80

            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.

            www.frankwilleke.de
            Only asking personal code questions here.

            1 Reply Last reply Reply Quote 0
            • ferdinandF
              ferdinand
              last edited by ferdinand

              Hi,

              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.

              Cheers
              zipit

              MAXON SDK Specialist
              developers.maxon.net

              1 Reply Last reply Reply Quote 0
              • fwilleke80F
                fwilleke80
                last edited by fwilleke80

                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.

                Thank you so much, that brought me back on track!

                Cheers,
                Frank

                www.frankwilleke.de
                Only asking personal code questions here.

                1 Reply Last reply Reply Quote 0
                • ferdinandF
                  ferdinand
                  last edited by

                  Hi,

                  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).

                  Cheers
                  zipit

                  MAXON SDK Specialist
                  developers.maxon.net

                  1 Reply Last reply Reply Quote 0
                  • fwilleke80F
                    fwilleke80
                    last edited by

                    I got it working now. Thank you! 🙂

                    www.frankwilleke.de
                    Only asking personal code questions here.

                    1 Reply Last reply Reply Quote 0
                    • r_giganteR
                      r_gigante
                      last edited by

                      Hi Frank, looks like I came too late here 🙂

                      Thanks @zipit and @fwilleke80 for running the conversation.
                      Couple of notes:

                      • do all the maths by using the UniversalDateTime as pointed in our documentation: I don't see any major advance to use the LocalDateTime
                      • use the maxon::UniversalDateTime::FromValues() to convert from year, month, day, hour, min, sec to maxon::UniversalDateTime representation
                      • in case also hours, mins and secs difference gets interesting you can easily extend the code to consider those differences
                      • consider that otherDate shouldn't be necessarily bigger than currentDate
                      • make proper use of error handling.

                      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\t@ days\n\t@ hours\n\t@ mins\n\t@ secs", currentUDate, otherUDate, days, hours, mins, secs);
                      	else
                      		DiagnosticOutput("Difference between @ and @ is \n\t@ days\n\t@ hours\n\t@ mins\n\t@ secs", otherUDate, currentUDate, days, hours, mins, secs);
                      	
                      	return maxon::OK;
                      

                      Cheers, R

                      1 Reply Last reply Reply Quote 1
                      • fwilleke80F
                        fwilleke80
                        last edited by

                        Thank you, Ricardo! 🙂

                        www.frankwilleke.de
                        Only asking personal code questions here.

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post