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.
apex 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:
apex DateTime a = DateTime.now(); DateTime b = DateTime.now().addHours(1); Boolean isLater = b > a; // true Long diffMs = b.getTime() - a.getTime(); // milliseconds
Formatting:
apex 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-local
Parsing:
apex 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.
