7

Consider the following unit test:

@istest
public static void datetests2() {
    Set<Date> dts = new Set<Date>();
    dts.add(DateTime.now().Date());
    dts.add(DateTime.now().addHours(1).Date());
    dts.add(DateTime.now().addHours(2).Date());
    system.debug(dts);

    system.assertEquals(1, dts.size());
}

The result, as I'm sure you'd expect would be that the test would pass. The debug statement showing something like:

14:49:36:002 USER_DEBUG [22]|DEBUG|{2019-05-01 00:00:00}

Now consider this very similar unit test:

@istest
public static void datetests() {
    Set<Date> dts = new Set<Date>();
    dts.add(Date.valueOf(DateTime.now()));
    dts.add(Date.valueOf(DateTime.now().addHours(1)));
    dts.add(Date.valueOf(DateTime.now().addHours(2)));
    system.debug(dts);

    system.assertEquals(1, dts.size());
}

You would expect it to pass. Well, I did. But in fact, it fails.

14:57:10:001 FATAL_ERROR System.AssertException: Assertion Failed: Expected: 1, Actual: 3

Displaying something like:

14:57:10:001 USER_DEBUG [10]|DEBUG|{2019-05-01 09:00:00, 2019-05-01 10:00:00, 2019-05-01 11:00:00}

Now, part of why this may be happening is clear - While logic suggests that Date.ValueOf returns a date, it actually seems to return a DateTime (which contradicts the docs, but whatever...)

In anonymous Apex:

system.debug(Date.ValueOf(DateTime.now()));

Returns at the moment:

15:00:24:002 USER_DEBUG [1]|DEBUG|2019-05-01 10:00:00

which is a datetime

But you'd really expect Set to enforce uniqueness across dates regardless, right?

I've searched online, known issues, etc. and didn't find anything obvious. I confess this completely caught me by surprise.

So my question are:

  1. Can you reproduce this?
  2. Can anyone find/show documentation that addresses this?
  3. Does anyone know if this has always been like this, or are we seeing a change in behavior?
  4. Any other thoughts or ideas?

Note - this testing is on a fresh SFDX scratch org running Spring 19 API 45. I did run the unit tests at API 40 just to make sure it wasn't a version artifact.

  • As a matter of interest, even without the bug this unit test will fail when the time is between 22:00 and 00:00 (exclusive) when the test is executed. – Phil W May 2 at 6:31
5

UPDATE

It seems to have been reported as a known issue here. Though the title says String.valueOf but the code sample in the details reflects what is being observed here.


This overall behavior is impacted because of Date.valueOf and not Set, as Set is behaving as expected. I think you will need to reach out to Salesforce Support (I will try to reach out as well) to report this behavior as the Date.valueOf should not return the timestamp values at the first place at least based on the documentation.

Details and explanation below as response to your questions.


  1. Can you reproduce this?

Yes. I was able to reproduce the behavior you have mentioned here.


  1. Can anyone find/show documentation that addresses this?

You may have (re)discovered a behavior (bug) here in the Date.valueOf method itself. There's a mention about the timestamp being returned in the docs (emphasis mine):

In API version 33.0 or earlier, if you call Date.valueOf with an object that represents a Datetime, the method returns a Date value that contains the hours, minutes, and seconds.

It just seems with the latest API version, it is behaving just like versions prior to 33.0 (as far as I can confirm)


  1. Does anyone know if this has always been like this, or are we seeing a change in behavior?

Based on the docs and the behavior, it seems this is a change in the expected behavior.


  1. Any other thoughts or ideas?

The behavior for Set is as expected. In your second test, you are able to add the values in the Set as they are still distinct because of the timestamp that is returned along with. And if there are distinct values, your Set contains 3 different values in that case. This definitely needs to be reported.

  • Regarding the behavior of set being as expected - shouldn't the fact that the Set is declared as type Date (Set<Date>) enforce uniqueness based on the Date part of the value? Intuitively, that is what I would expect... – kibitzer May 2 at 1:12
  • Ideally yes but I think because the data in the set is still unique, it works on the data itself. And that based on the docs prior to v34.0 and the known issue, because a Date could still contain the timestamp values, the Set itself seems to be acting upon the data it contains. – Jayant Das May 2 at 1:14

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.