I strongly recommend that instead of messing with the system clock, you bite the bullet and refactor that legacy code to use a replaceable clock. Ideally that should be done with dependency injection, but even if you used a replaceable singleton you would gain testability.
This could almost be automated with search and replace for the singleton version:
- Replace
Calendar.getInstance()
withClock.getInstance().getCalendarInstance()
. - Replace
new Date()
withClock.getInstance().newDate()
- Replace
System.currentTimeMillis()
withClock.getInstance().currentTimeMillis()
(etc as required)
Once you’ve taken that first step, you can replace the singleton with DI a bit at a time.