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