Datetime nightmare, any thorough module or control in C# to help ease the pain?
once again I have to create a date module, and once again i live the horror of perfecting it, is it me or are date and time the filthiest animals in programming profession, its the beast lurking behind the door that I wish I never have to deal with :(
does anyone know of a great source I can learn from that deals with dates in the following aspects:
- user enters datetime and time zone
- system translates to universal time and saves in data source
- system retrieves universal time converted to local time chosen by developer (not by server or client location which may not be the right zone to 开发者_如何学Pythondisplay)
- system should consider daylight time saving differences
- cannot rely on "DateTime" parsing as it parses bohemiangly with respect to local server time
- must give ability to developer to deal in both shapes: datetime and string objects
i looked at blogengine.net to see how they deal with but its too nieve, they save the time difference in hours in the settings datasource, it is absoluteley inaccurate... any sources to help?
i already went far in creating the necessary methods that use CultureInfo, TimeZoneInfo, DateTimeOffset ... yet when i put it to the test, it failed! appreciate the help
EDIT:
After squeezing some more, i narrowed it down to this:
public string PrettyDate(DateTime s, string format)
{
// this one parses to local then returns according to timezone as a string
s = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(s, "AUS Eastern Standard Time");
CultureInfo Culture = CultureInfo.CreateSpecificCulture("en-au");
return s.ToString(format , Culture);
}
problem is, I know the passed date is UTC time because im using
DateTimeOffset.Parse(s, _dtfi).UtcDateTime;
// where dtfi has "yyyy-MM-ddTHH:mmzzz" as its FullDateTimePattern
when i call the function on my datetime, like this:
AuDate.Instance.PrettyDate(el.EventDate,"yyyy-MM-dd HH:mm zzz");
on my machine i get:
2009-11-26 15:01 +11:00
on server I get:
2009-11-26 15:01 -08:00
I find this very peculiar! why is the timezone incorrect? everything else is in place! have i missed something?
My comments for your pointers.
user enters datetime and time zone
@ OK no issuesystem translates to universal time and saves in data source
@ OK no issuesystem retrieves universal time converted to local time chosen by developer (not by server or client location which may not be the right zone to display)
@ Is this s requirement? Why not just retrieve as universal timesystem should consider daylight time saving differences
@ Can be handled by DaylightTime Class, TimeZone Class etccannot rely on "DateTime" parsing as it parses bohemiangly with respect to local server time
@ Then do not rely on DateTime Parsingmust give ability to developer to deal in both shapes: datetime and string objects
@ DateTime Class as the basis should be good enough, use TimeZone / TimeZoneInfo / DaylightTime / DateTimeOffset etc to augment it
I feel your pain - which is why I'm part of the Noda Time project to bring a fully-featured date and time API to .NET. However, that's just getting off the ground. If you're still stuck in a year's time, hopefully Noda Time will be the answer :)
The normal .NET situation is better than it was now that we've got DateTimeOffset
and TimeZoneInfo
, but it's still somewhat lacking.
So long as you use TimeZoneInfo
correctly twice, however, it should be fine. I'm not sure that DateTime
parsing should be too bad - I think it should parse it as DateTimeKind.Unspecified
unless you specify anything else in the data. You can then convert it to UTC using TimeZoneInfo
.
Could you provide a short but complete program which shows the problems you're having?
Actually, I find the .NET date/time functionality to be quite nice. I'm puzzled by your troubles with it.
What exactly are you trying to do that DateTimeOffset
and TimeZoneInfo
can't do for you?
- "User enters datetime and timezone" -- Check! Either
DateTime
orDateTimeOffset
would work here. - "System translates to universal time and saves in data source" -- Check! Again, either
DateTime
orDateTimeOffset
would work for you, although most database backends will need some special handling if you want to store timezone offsets. If you're already converting it to UTC, just store it as adatetime
field in SQL Server or the equivalent in another RDBMS and don't worry about storing the fact that it's UTC. - "System retrieves universal time converted to local time chosen by the developer" -- Check! Just construct a
TimeZoneInfo
for your desired local time, and then callTimeZoneInfo.ConvertTime
. - "System should consider daylight time saving differences" -- Check! That's what
TimeZoneInfo.AdjustmentRule
is for. - "Cannot rely on "DateTime" parsing as it parses bohemiangly with respect to local server time" -- ??? First off, "bohemiangly" isn't even a word. And you can customize how the datetime gets parsed with
DateTime.ParseExact
. - "Must give ability to developer to deal in both shapes: datetime and string objects" -- Why? What's wrong with just keeping one internal representation and then transforming only on input and output? I can't think of any operation on date/time values that would be made easier by doing it against a string.
In short, I think you're just griping about the complexities of handling date/time data in general.
Thanks to Jon Skeet who put me on the right track, i never knew this before but now I know, DateTime
object does not hold time zone information in it AT ALL! so whenever i use it i am already losing the datetime offset information, the DateTimeOffset
object however, retains the time zone bit, so all my objects should use that, i really thought datetimeoffset
object to be a bit limiting, i wanted to post a question about what is different between datetime
and datetimeoffset
, i should have done that!
now Im using the following code to retrieve the right zone:
string s = "2009-11-26T04:01:00.0000000Z";
DateTimeOffset d = DateTimeOffset.Parse(s);
TimeZoneInfo LocalTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
DateTimeOffset newdate = TimeZoneInfo.ConvertTime(d, LocalTimeZoneInfo);
return newdate.ToString("yyyy-MM-dd HH:mm zzz");
thank you all for your input
精彩评论