6

Maybe the answer is so obvious, I'm not seeing it, but I have a question that I'll risk asking anyway.

I want to allow users of a .NET Web application to enter a date/time, store it in an Oracle database, and no matter which timezone they are in, it always displays as the raw, original version as typed in by the user. So if one user in California enters 2PM and another in Maryland enters 2PM, they would both show as 2PM to a user in Japan. Two types of clients are possible, a web user and a windows client user (connected via web service).

Think of it like I want to completely break all timezone smarts that most applications worry about.

I don't want to save as a string though. I want a datetime that I can add/remove hours and minutes from.

Edit:

This was basically the exact problem I was having.

Rake36
  • 992
  • 2
  • 10
  • 17
  • Related question: http://stackoverflow.com/q/2532729/1583 – Oded Sep 10 '11 at 21:14
  • What exactly are you having difficulties with? – Oded Sep 10 '11 at 21:16
  • 1
    This has 95% odds of Something You'll Deeply Regret Some Day. But trivial to implement, just use the time entered by the user locally without otherwise trying to convert it. DateTime.Parse() if you get a string. You can't do this on the server, you don't know where the intertube started. – Hans Passant Sep 10 '11 at 21:24
  • It's for scientific data entry. They want the value stored to be exactly as entered. They consider timezone manipulation to be 'altering' the data. We keep a separate audit trail that DOES care about timezone. – Rake36 Sep 10 '11 at 21:37
  • @Oded: The windows client is saving datetimes with the timezone offset changing the value stored in the oracle db. So 2PM California is showing up on the web server as 5PM EST (which you would normally want I know). – Rake36 Sep 10 '11 at 21:39
  • This is strange. Normally dates are saved "as is". Are you using an ORM? Try looking at the `DateTime.Kind`. Normally it's "Unspecified". – xanatos Sep 11 '11 at 06:56

4 Answers4

12

You should always store DateTime in UTC format (universal). When you display it you can choose which ever timezone you wish, in your case this can be fixed for all users, rather than based on location.

// when recording date time
DateTime utcDateTime = DateTime.UtcNow;

// parse DateTime back out from string
DateTime utcDateTime = DateTime.SpecifyKind(DateTime.Parse(dateStr),
                                            DateTimeKind.Utc);

// localized DateTime
DateTime localDate = utcDateTime.ToLocalTime();

// fixed DateTime based on timezone
string timeZoneKey = "New Zealand Standard Time";
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneKey);
DateTime nzlocalDate = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, timeZone);

This takes into account things like day-light savings which can trip you up if start saving localized dates.

TheCodeKing
  • 19,064
  • 3
  • 47
  • 70
  • 1
    Based on my poorly worded question, I'm accepting this as best answer. It's what the application should be doing, but I'll have to work around some architectural issues. Plus, this is in .NET 2.0 - so TimeZoneInfo is not available to me just yet. – Rake36 Sep 10 '11 at 23:10
1

If you just store the DateTime as entered/picked by the user then it will be stored as just that. There will be time zone informations stored in it, but you are in control of what you do with it.

For example, when you want to output it to the screen/file etc. you will need to format it to a string. If you use this ToString overload with CultureInfo.InvariantCulture then this should ignore the current culture and output the date as is:

DateTime date = DateTime.Now;
string output = date.ToString("d", CultureInfo.InvariantCulture);

Other operations will require different handling, but you will need to specify what happens in each case.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
0

I had a time sensitive fix and the SpecifyKind did not allow me to make proper TimeSpan comparisons. In my situation, the quickest solution was to simply remove the Hours, Minutes, and Seconds from the time, as the DateTime I was comparing with was at midnight (00:00:00),

DateTime eventDateTime = (DateTime)row["event_date"];
eventDateTime = eventDateTime.AddHours(-1 * eventDateTime.Hour).AddMinutes(-1 * eventDateTime.Minute).AddSeconds(-1 * eventDateTime.Second);
Jason Hitchings
  • 667
  • 8
  • 10
0

If you really want discard time zone:

    public static DateTime WithoutTimeZone(this DateTime dateTime)
    {
        if (dateTime.Kind != DateTimeKind.Unspecified)
            return new DateTime(dateTime.Ticks, DateTimeKind.Unspecified);

        return dateTime;
    }
adospace
  • 1,841
  • 1
  • 17
  • 15