Three distinct types:
- Date — calendar date with no time (e.g.,
Date.newInstance(2026, 5, 1)). - Time — clock time with no date.
- DateTime — date + time + timezone.
Date today = Date.today();
DateTime now = DateTime.now();
DateTime utc = DateTime.newInstanceGmt(2026, 5, 1, 12, 0, 0);
DateTime local = DateTime.newInstance(2026, 5, 1, 12, 0, 0);Critical timezone behaviour:
- `DateTime.now()` returns current time in GMT/UTC.
- `Date.today()` returns today in the running user's timezone.
- `Date.toStartOfMonth()` etc. operate in the user's timezone.
This split causes confusion: a job running at "midnight UTC" and a job running at "midnight in user's timezone" can fire at different times.
Comparing:
DateTime a = DateTime.now();
DateTime b = DateTime.now().addHours(1);
Boolean isLater = b > a; // true
Long diffMs = b.getTime() - a.getTime(); // millisecondsFormatting:
String iso = now.format('yyyy-MM-dd''T''HH:mm:ssZ'); // ISO 8601
String custom = now.format('MMM d, yyyy'); // "May 1, 2026"
String userTz = now.format('h:mm a', UserInfo.getTimeZone().getID()); // user-localParsing:
DateTime parsed = DateTime.parse('2026-05-01 12:00:00');
DateTime jsonDate = (DateTime) JSON.deserialize('"2026-05-01T12:00:00.000Z"', DateTime.class);Common pitfalls:
- Mixing user-timezone and UTC when computing differences.
- SOQL date literals (
TODAY,LAST_N_DAYS:30) honour user timezone — same query gives different results for users in different zones. - Daylight saving transitions can cause hour-arithmetic surprises.
Always: store DateTime as UTC; convert to user timezone only for display.