DateTime.ToString("yyyy-MM-dd")

Recently I found the answer to two very hard questions about bugs in dasBlog. They were kinda tricky to figure out, but also really interesting (bug 2 will be in a follow up post)

Bug 1: DateTime.ToString()

One of the classes in dasBlog that stores information like Comments, Trackbacks and Pingbacks determines it's filename like so:

public string FileName
{
get
{
return DateUtc.ToString("yyyy-MM-dd") + ".dayextra.xml";
}
}

Well a few weeks ago Scott Hanselman emailed me with some files with names like 1425-05-05.dayextra. Can you figure out why this is?

Well as I found out, DateTime always assumes Gregorian Calendar, so DateTime.ToString() will output a filename with a Culture.Invariant filename. Well what happened to Scott is that he got comment spammed by some one who's Windows Region was set to a Culture that uses the Hijri Calendar. So, 1425-05-05 is the equivalent of 2004-06-22.

The reason this happened was because this person happened to be the first person to leave a comment, and thus the file was created using the CultureInfo from their machine!

The fix was to do the following:

public string FileName
{
get
{
// Use Invariant Culture, not host culture (or user override),
// for date formats.
IFormatProvider mmddFormat = new CultureInfo(String.Empty, false);

// Ignore local DateFormatInfo (could say CCYY-DD-MM),
// always use CCYY-MM-DD.
return DateUtc.ToString("yyyy-MM-dd", mmddFormat) + ".dayfeedback.xml";
}
}

DateTime stuff is very tricky and dasBlog has 4 different kinds of DateTime so it can get confusing.

  1. DateTime for Server (timezone the server is in)
  2. DateTime for Author (timezone the author is creating the post)
  3. UTC, which is how all data is saved
  4. Browser DateTime (where the reader is reading the post)

In all these cases dasBlog must know how to convert back and forth between all these formats and preserving the window of time that equals a single Day (24 hours of time, in the server, author, or UTC timezone).