4

Attempting to implement a formula similar to that outlined here, namely where check a box if NOW() - CreatedDate is more than a couple seconds.

I originally had ((NOW()-CreatedDate)*10000) > 1, because that's what was in the post and I didn't really know how to prove it, and it seemed about right.

Debugging something and wanted to prove it - I'm working in anonymous apex to figure out what the threshold exactly should be for 5 seconds and put together the following:

Datetime dateOne = Datetime.newInstance(2018, 10, 20, 0, 0, 0);
Datetime dateTwo = Datetime.newInstance(2018, 10, 20, 0, 0, 5);
Decimal difference = dateTwo.getTime() - dateOne.getTime();
System.debug(difference);

That prints at 5000 though, so I don't understand why the post was multiplying the difference between the dates by 10,000. My thought was that this was simply an error on the OPs part, but the part of their post where they say they refreshed a page and got 0.000081 seems impossible if they are actually off by a magnitude of 10,000 or more -- so I assume the error is in my anonymous apex and not with the OP.

My next thought was perhaps I shouldn't be using "Decimal" so I switched that fourth line to

Integer difference = dateTwo.getTime() - dateOne.getTime();

but then I get an error about "Illegal assignment from Long to Integer". I read the definition of long from the documentation but it's totally over my head. Is the 5000 difference I'm getting technically in "long" format? And does that mean it's actually a decimal without a decimal point and is really something more like 0.00005000 and I just can't tell because of how I've written this?

What my basic end goal is is to have a formula that can evaluate to exactly 5 seconds, but I'd really like to comprehend it vs. just being given something that I can copy paste. Can anyone explain what I'm missing here? My background isn't in CS/I'm self-taught, so I'm trying to wrap my head around what I don't know.

Thank you!

1
  • 1
    The long is in milliseconds so 5000 should be 5 seconds or 5000 miliseconds – Eric Oct 22 '18 at 0:23
3

Subtracting Dates in Formulas

A formula returns the number of days between two dates. To get sub-day accuracy (e.g. hours), we typically multiply by the unit we're interested in. For example, to get the number of hours between two days, multiply by 24, or for minutes, 1,440. Your multiplication of 10,000 gives you a granularity of about 8.64 seconds.

Integer Numbers

The two types, Integer and Long, are types of integer values (in the mathematical sense). They can only hold "whole" numbers within their value range. Dividing two integers will discard the fractional result. For example, 5 / 2 is 2, and 100 / 12 is 8. The fractional part is discarded.

Decimal Numbers

The Float and Decimal types use decimal points, and can therefore hold fractional numbers. Double is the smaller of the two, and not really used in most cases. The Decimal type is used for all standard and custom number fields in Salesforce.

32-Bit Numbers

An Integer holds 32-bits worth of data. A bit is a "binary digit", consisting of either 1 or a 0. The maximum range of 32-bits is -2,147,483,648 to 2,147,483,647 (0 is considered positive, which is why the upper range is 1 less). This value is large enough for about 24 days of time in millseconds.

64-Bit Numbers

A Long holds 64-bits worth of data. The maximum range here is -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807, again, because zero occupies one positive number value, the positive maximum is one less. This value is able to hold time values of up to about 292,277,024 years, much larger than anything you'd ever need to use.

Milliseconds

A millisecond is 1/1000th of a second. 1000 of these is one second. This is the value returned by DateTime.getTime(), the number of milliseconds that have occurred since the Epoch, defined as January 1st, 1970 (why is historical, just know that's a kind of standard measurement of time). This is usually not very useful to us, so the first thing we do is divide by 1,000 to end up with seconds, instead.

Coercing Large Values in to Small Values

By default, Apex code won't automatically put a larger value into a smaller storage space. This prevents data truncation. As a simple example, if you have a 64-bit number, you can't put it into a 32-bit value, because it would be cut off. You can visualize it like this:

 Integer ABC:                                        #### #### #### #### #### #### #### ####
 Long ABCD  :0001 0110 0011 1001 0001 0110 0011 1001 0001 0110 0011 1001 0001 0110 0011 1001 

Where "#" shows one available space for a bit. As this kind of shows, if you try to put all 64-bits into a 32-bit space, they can't all fit. There's simply no space for the remaining bits. The result would be that the value is truncated to fit in the available space:

 // Long ABCD = __some_value__;
 // Integer ABC = ABCD;
 Long ABCD  :0001 0110 0011 1001 0001 0110 0011 1001 0001 0110 0011 1001 0001 0110 0011 1001 
 Integer ABC:                                        0001 0110 0011 1001 0001 0110 0011 1001

This is usually a logic error, and a bug, because now we're changing a much larger value into a much smaller value because some of the data was lost.

The compiler detects this problem for us and tells us it can't be done. We can override this "type safety" feature, but again, if we do so with really large values, it can cause inaccurate values, just as if we'd taken the remainder of dividing by 2^32.

The Solution

The solution, of course, is to use the Long data type for the variable you're using. This will prevent the "24-day truncation" from affecting your code in very subtle ways, and eliminates the error about an illegal assignment.

Long difference = dateTwo.getTime() - dateOne.getTime();

So, the value of 5,000 means 5,000 millseconds, or just 5 normal seconds. As mentioned earlier, if we're interested in smaller than a second increments, this is useful, but in most cases, we just divide by 1,000 to get a normal value we're used to: seconds.

There's lots of reading you get in to if you're interested in learning more, such as about the various data types, how to willfully tell Apex code to truncate data via casting (but be aware of runtime errors and logic errors if you're not careful), and so on. Also remember there's lots of great trails on the trailhead if you're interested in getting serious Apex code.

1
  • Such a great blog article! – kurunve Oct 22 '18 at 8:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.