I've just spent two days banging my head against the Salesforce wall, and the problem came down to this:

Date wkStart = Date.newInstance(2019,10,12);
Datetime wkStart1 = wkStart;
Datetime wkStart2 = Datetime.newInstance(wkStart,Time.newInstance(0,0,0,0));

wkStart1 and wkStart2 are not equal, at least in my non-GMT timezone. It appears that the implicit cast sets it to midnight GMT, while the explicit newInstance sets it to midnight my time zone. (An explicit cast behaves the same as the implicit cast.)

Is there a logic behind that? Why would an implicit midnight be interpreted differently than an explicit midnight? Further, is that documented somewhere? I've searched all I can think of to search on in the Apex manual, and haven't been able to find anything.


Yes, this is a problematic behavior that does exist. No, it is not documented (that I'm aware of), and cannot likely ever be fixed without causing hammer fails. It's something you, a developer, needs to be aware of once you run in to it, and avoid this situation. Basically, do not ever compare a Date to a DateTime and expect to get a correct comparison/conversion, and do not convert a Date to a DateTime implicitly, even though it's "legally" allowed by the runtime. The only way you can compare a Date and a DateTime legally is to call the "date" method:

Date wkStart = Date.newInstance(2019,10,12);
Datetime wkStart2 = Datetime.newInstance(wkStart,Time.newInstance(0,0,0,0));
Boolean areEqualDates = wkStart2.date() == wkStart;

The date() method should return the same value for all time periods within the same day, thus returning a true value. You'll still need to be aware of certain situations, as it is time-zone dependent. Always compare GMT to GMT or local-time to local-time, and do not mix the two.

  • Speaking of "GMT to GMT or local-time to local-time", how can you tell which is which? SF persists in confusing the issue. With the above wkstart2, even though I know it's assigning midnight my time, a subsequent System.debug('wkstart2='+wkstart2) shows the time in GMT. (And if that should be another question, I'll be glad to make it one.) – vr8ce Oct 14 '19 at 5:54
  • @vr8ce Basically, if you call a GMT-based method (e.g. DateTime.newInstanceGMT, or if you query from the database, it's GMT, otherwise it's local time. System.debug is misleading because it's always GMT if you debug the datetime object directly. The only way to know for sure is to check the docs for which is which (one of the main reasons why I still frequently use the docs even with 14+ years experience in SFDC). – sfdcfox Oct 14 '19 at 14:08

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.