Proposal for custom time string formatting in std.datetime
Jonathan M Davis
jmdavisProg at gmx.com
Fri Dec 23 16:07:22 PST 2011
On Friday, December 23, 2011 09:36:14 Michel Fortin wrote:
> Well, what I'm getting at is that most of the time you don't care which
> time zone the time was recorded in, so you don't need to attach a time
> zone to it, you only need to take the time zone into consideration when
> formatting as a string, and then you mostly always use local time.
>
> The real issue remains that you can't use SysTime without including all
> the code for all the time zones. Think about this: if you don't need to
> carry around the time zones but instead only ask for a time zone when
> formatting as a string, you much less need time zones to be
> polymorphic. The time zone could be a template argument to the
> formatting functions for instance.
>
> On the other hand, if you need to carry the associated time zone along
> with the time, then things gets more complicated and a polymorphic time
> zone type tend to solve that problem well. But how many of us need to
> carry a time zone with a time value?
>
> So in my opinion associating a time zone with SysTime was a mistake.
> Not just because it forces you to carry around an extra pointer, but
> mostly because it forces time zones to be polymorphic which brings all
> the drawbacks of a class: less inlining and worse performance due to
> virtual functions, and all the virtual functions need to be included in
> the binary even if you don't use them. It does benefit the use case
> where you need to tag a time with a specific time zone, but that sounds
> rather specialized to me.
The core issue with not carrying around a time zone is that you get conversion
problems. People do dumb stuff like convert time_t values from UTC to local
time and back again, which causes all kinds of bugs. For most time zones, you
cannot convert them back to UTC correctly in the general case. The hours when
DST switches occur screw that up. So, in order to handle time correctly, you
need to always keep it in UTC until you need to present it (e.g. converting it
to a string) or need to know something about its date (such as what year or
month it's in). If you're actually storing a converted time value, you're
doing it wrong and will almost inevitably have bugs. I did std.datetime in the
first place, because I was sick of having to fix time-related bugs at work and
wanted D to get it right. That requires a type which holds the time in UTC and
knows its time zone.
Now, "knowing its time zone" can be dealt with in several ways. One way is to
integrate it into the type. Your proposed UTCTime would do that. It's always
in UTC. You could also have another type which was called something like
LocalTime which held the time in UTC internally but any functions on it which
needed time zone conversions used the appropriate calculations for the local
time zone instead of UTC. There are three problems with that approach though.
1. It doesn't scale.
2. You have to care about the time zone of the time object when you pass it to
functions.
3. Code duplication.
#1 isn't really a big deal if all you care about is UTC and local time.
Dealing with other time zones can be very useful, but is definitely more of a
niche issue. It's not all that hard to end up in situations where it matters
though when you're getting data from another computer. There are lots of
applications out there which have to deal with that, but I don't know how
common it ulimately is. Certainly, where I work, we have to do it all the
time. And I know that Adam Ruppe has to deal with similar issues with his web
software based on questions he asked about std.datetime previously.
#2 can be dealt with with templates to some extent, but functions still still
have to return a specific time type. So, unless you do something like make it
so that you pass the type you want returned as a template argument, you have
to deal with a specific time type and potentially convert it to whichever one
you actually want. This isn't necessarily a big deal, but it does complicate
things. With a solution like SysTime, you don't generally have to care what
the time zone of a particular SysTime actually is.
#3 can be dealt with in several ways - including using a bunch of free
functions instead of having the functions on the types themselves, but that's
no OO at all, and highly ugly IMHO. Mixins would be a better approach, but
regardless, you have to deal with the fact that you're having to effectively
define a bunch of functions multiple times.
So, all around, a solution where the time zone is treated as a property of the
type which can be changed seems like a much cleaner solution to me. It's also
much more flexible and powerful, because you _can_ then define more time zones
than just two. The current solution handles time correctly without generally
requiring the programmer to care about what time zone the time is in and yet
still allows for more advanced time zone usage if the programmer wants it.
The only real downside that I see here is that for those trying to keep their
executables as absolutely small as possible and don't care about anything
beyond comparing file times end up with a larger executable due to features
that they don't care about. My greatest fear here is that we would be pushed
into an inferior solution which would increase the likelihood of bugs just
because some folks want a slightly smaller executable.
- Jonathan M Davis
More information about the Digitalmars-d
mailing list