Have you tried looking at DateTimeZone::getTransitions() ?
http://www.php.net/manual/en/datetimezone.gettransitions.php
In particular use the [offset] and [isdst] properties.
- When they save the time, find the first transition before the current date that is NOT DST. (Typically one of the two values in the past year). Convert using the offset of the non-DST period
- When retrieving the value and you are currently in a DST period use the offset of a non-DST period to translate the time, not the current offset.
Taking your EST example, in August even though you are in EDT, you save values using the EST conversion of -5.
When pulling the value back out if they view that value in January you add 5, and if you are in August you add 4.
This will work for 95% of cases I'm assuming that the switches are consistent. If Eastern decided to merge with Central, you could have transitions that run –5/–4/–5/–4/–5/–5/–6/–5/–6/–6 and that would mess things up.
There's no magic bullet for this one. I don't know the details of your app structure, you may just have to try adding 3 hours to the midnight of whatever day you are on so that any recurring daily appointment is stored as a time only.