Okay. Here is my current datetime code for review. It's not 100% done, but I think that it's ready to be reviewed. The one part that is not yet complete is the PosixTimeZone and WindowsTimeZone classes which allow you to get TimeZone objects for arbitrary time zones by name on Posix and Windows systems respectively. It's functionality that I definitely think should be in std.datetime, but it's not necessary for most programs, and this project has already taken me far longer than I ever anticipated, so it seems prudent to present my code with PosixTimeZone and WindowsTimeZone stubbed out (but everything else being complete) and finish them later. If the review process takes long enough, I may have them done before it's over anyway.
There are several TODO comments in the code which mark functionality which probably should be added at some point, but it's not core functionality, and I never intended to implement any of it before submitting my code for review (for instance, it would be useful to implement date recurrence patterns and be able to create ranges out of them - useful, but hardly core functionality and potentially very time-consuming to implement). My code is based on Boost's API, but it isn't exactly the same and expands on it a fair bit, and none of the implementation is from Boost. It's also been properly D-ified, with it being highly generic and having ranges and the like. Since the module was pushing 40,000 lines, I split it into separate modules in a single package: * datetime.all: Has a description for the package as a whole and publicly imports all of the other modules in datetime. Ideally, you'd just import datetime.all rather than trying to selectively import the other modules. * datetime.core: Contains types and functions which are used by most of the other modules in datetime (e.g. the enum TUnit which hold the various units of time: year, hour, second, etc.). * datetime.duration: Contains the various duration types. * datetime.interval: Contains the various interval and range types. * datetime.other: Contains stuff that doesn't fit in in any of the other modules. * datetime.timepoint: Contains the various time point types. It also contains Clock, which will give you the current time. * datetime.timezone: Contains the various time zone classes which SysTime uses. Rather than Boost's date, ptime, and localtime, I have Date, TimeOfDay, DateTime, and SysTime. * Date holds a Gregorian date as year, month, and day and is optimized for calendar operations. It has a range of approximately 32,000 BC to 32,000 AD. * TimeOfDay holds hour, minute, and second. * DateTime holds a Date and a TimeOfDay to have a date with the time. It's optimized for calendar operations and has no concept of time zone. * SysTime is intended to be the time type to deal with time from the OS. It is more or less a combination of Boost's ptime and localtime. It holds the date/time in hecto-nanoseconds (100 ns) from midnight January 1st, 1 AD UTC and has a TimeZone object as part of it so that its getters can convert the time to that time zone. However, its internal time is always in UTC, thereby avoiding conversion errors due to DST. Its constructors default to using the LocalTime TimeZone object, so if you don't want to worry about time zones, you don't have to. The Clock object allows you to get a SysTime with the current time in local time, UTC, or any other time zone that you give it. SysTime has a range of approximately 29,000 BC to 29,000 AD. One of the major changes from Boost is that I dropped special time points - that is positive infinity, negative infinity, and invalid (e.g. not-a-date). They complicated the code considerably and their only benefit, as far as I can tell, is to aid in defining infinite intervals and ranges. And since infinite ranges in D need to be known as infinite at compile time, it's not possible to define infinite ranges based on their end points (which are known at runtime). So, I just defined interval and range types which were infinite (in addition to the finite ones) and dropped the special time points. Another major change is that all duration, interval, and range types (rather than iterator types) are generic and are intended to work with pretty much any time point instead of being specific to particular time point type (though there are some restrictions due to the fact that you can't convert between months/years and smaller time units due to the variable number of days in a month and year). Also, ranges are defined based on delegates, so they are extremely flexible. I have already integrated SHOO's code from the nascent std.datetime with minimal alterations. Ticks became TickDuration and was put in datetime.duration. systime and apptime became Clock.currSystemTicks and Clock.currAppTicks respectively and were put in datetime.timepoint. The rest is in datetime.other (which is painfully small, but what's there doesn't really fit in in any of the other modules; however, it may grow when additional functionality is added, and it seems to me that the fact that the intended use is to just import datetime.all makes the small module less of an issue). I didn't make much of an attempt to make my code use @safe, @trusted, or @system, since making that work is definitely a pain at the moment. std.array, std.algorithm, std.range, and std.conv (at minimum) really should be made to use them first. I did try and use const, nothrow, and pure liberally, though with the current purity rules, a lot of functions which should be pure can't be (though the svn version of dmd should do better), and bug http://d.puremagic.com/issues/show_bug.cgi?id=4974 doesn't help either. I have included my src files as well as the ddoc html files generated from them. In addition to datetime, I have included a unittests module which I use heavily in my unit tests (and makes them much more pleasant). I'd love it if some version of that got into Phobos as well. My code has extensive unit tests and should be fully documented, so bugs should be few and far between (though I'm not about to claim that my code is bug-free). The code: https://docs.google.com/leaf?id=0B- f1J0HiG2ovYmMzYWVkODMtODRiYi00NTg4LWI4MDctOTQ0MjE4YTI5Y2U1&sort=name&layout=list&num=50 (the hyphen after the B is part of the link; I wish that I could get my client to wrap the normal lines but not the link...) - Jonathan M Davis P.S. If anyone can figure out how to make SysTime work as immutable, I'd really appreciate it. It holds a long value and an immutable TimeOfDay object in a Rebindable struct, so it should be able to be immutable, but I can't seem to get it to work, and I had to comment out all of my unit tests that verify that immutable SysTimes work. Also, if anyone could tell me what the default directories for the time zone files on FreeBSD and OSX are, that would be very useful. It's /usr/shar/zoneinfo on Linux, but I have no idea where they are on FreeBSD or OSX. _______________________________________________ phobos mailing list [email protected] http://lists.puremagic.com/mailman/listinfo/phobos
