Most business applications require manipulating dates and times:
- A subscription service adds one month to calculate the next billing date.
- A project management tool adjusts deadlines by days or weeks.
- A banking system sets expiry dates for credit cards.
A common mistake developers make is mutating date objects (like with java.util.Date
), leading to bugs in multi-threaded environments. The modern java.time
API avoids this by providing immutable classes and intuitive methods: plus()
, minus()
, and with()
.
1. Adding Time with plus()
LocalDate today = LocalDate.now();
LocalDate nextWeek = today.plusWeeks(1);
LocalDate nextMonth = today.plusMonths(1);
LocalDate nextYear = today.plusYears(1);
System.out.println("Today: " + today);
System.out.println("Next Week: " + nextWeek);
System.out.println("Next Month: " + nextMonth);
System.out.println("Next Year: " + nextYear);
✅ Great for scheduling future events.
2. Subtracting Time with minus()
LocalDateTime now = LocalDateTime.now();
LocalDateTime yesterday = now.minusDays(1);
LocalDateTime lastHour = now.minusHours(1);
System.out.println("Now: " + now);
System.out.println("Yesterday: " + yesterday);
System.out.println("Last Hour: " + lastHour);
✅ Perfect for expiry checks and log filtering.
3. Adjusting Fields with with()
LocalDate date = LocalDate.of(2025, 8, 28);
LocalDate adjusted = date.withDayOfMonth(1).withMonth(12);
System.out.println("Original: " + date);
System.out.println("Adjusted: " + adjusted);
✅ with()
lets you replace specific fields—useful for normalizing values (e.g., start of month).
4. Combining plus, minus, and with
ZonedDateTime meeting = ZonedDateTime.now(ZoneId.of("Europe/London"))
.plusDays(10)
.withHour(9)
.withMinute(30)
.minusHours(1);
System.out.println("Meeting Scheduled: " + meeting);
✅ Enables complex scheduling logic with chained calls.
5. Common Pitfalls and Anti-Patterns
- ❌ Forgetting immutability →
plus()
andminus()
return new objects. - ❌ Using legacy APIs (
Calendar.add()
) → error-prone and mutable. - ❌ Misusing
with()
→ accidentally setting invalid values (e.g., day 31 in February). - ❌ Not accounting for time zones with
ZonedDateTime
.
6. Best Practices
- ✅ Always store results of
plus()
,minus()
,with()
in new variables. - ✅ Use
with(TemporalAdjuster)
for advanced adjustments (e.g., last day of month). - ✅ Prefer
ZonedDateTime
when working across time zones. - ✅ Validate user input when applying adjustments.
📌 What's New in Java Versions?
- Java 8: Introduced
plus
,minus
, andwith
injava.time
. - Java 11: Improved
with(TemporalAdjuster)
features. - Java 17: Minor optimizations, stable API.
- Java 21: No major changes—API remains reliable.
✅ These methods have been stable since Java 8.
Real-World Analogy
Think of plus
, minus
, and with
like planning a journey:
plus()
→ Add extra days to your trip.minus()
→ Cut a day short.with()
→ Change the destination or start time.
Each change creates a new plan (object), leaving the original untouched.
Conclusion + Key Takeaways
- ❌ Don’t mutate legacy
Date
/Calendar
objects. - ✅ Use
plus()
,minus()
, andwith()
for clear and immutable date-time manipulation. - ✅ Chain methods for complex adjustments.
- ✅ Always consider time zones when working globally.
Immutability ensures safety, reliability, and correctness in business-critical applications.
FAQ: Expert-Level Q&A
1. Do plus/minus methods mutate objects?
No—they return new immutable instances.
2. How to set a date to the last day of the month?
Use with(TemporalAdjusters.lastDayOfMonth())
.
3. Can I add fractional units like 2.5 days?
No—units are whole numbers. Use Duration
for finer adjustments.
4. Is with() the same as plus()?
No—with()
replaces a field; plus()
adds a duration.
5. How do I avoid invalid adjustments with with()?
Wrap with exception handling (DateTimeException
).
6. Can I chain plus and minus?
Yes—methods are designed for fluent chaining.
7. How to adjust across time zones safely?
Use ZonedDateTime
with ZoneId
.
8. Are these methods thread-safe?
Yes—java.time
classes are immutable.
9. Can TemporalAdjuster be customized?
Yes, implement TemporalAdjuster
for custom rules.
10. Is it safe to cache DateTimeFormatter for adjusted dates?
Yes—formatters are immutable and thread-safe.