static public DateTime ToDateTime (ASN1 time)
{
if (time == null)
throw new ArgumentNullException ("time");
string t = Encoding.ASCII.GetString (time.Value);
// to support both UTCTime and GeneralizedTime (and not so common format)
string mask = null;
int year;
#if !NET_2_0
bool utc = true;
#endif
switch (t.Length) {
case 11:
// illegal format, still it's supported for compatibility
mask = "yyMMddHHmmZ";
break;
case 13:
// RFC3280: 4.1.2.5.1 UTCTime
year = Convert.ToInt16 (t.Substring (0, 2), CultureInfo.InvariantCulture);
// Where YY is greater than or equal to 50, the
// year SHALL be interpreted as 19YY; and
// Where YY is less than 50, the year SHALL be
// interpreted as 20YY.
if (year >= 50)
t = "19" + t;
else
t = "20" + t;
mask = "yyyyMMddHHmmssZ";
break;
case 15:
mask = "yyyyMMddHHmmssZ"; // GeneralizedTime
break;
case 17:
// another illegal format (990630000000+1000), again supported for compatibility
year = Convert.ToInt16 (t.Substring (0, 2), CultureInfo.InvariantCulture);
string century = (year >= 50) ? "19" : "20";
// ASN.1 (see ITU X.680 section 43.3) deals with offset differently than .NET
char sign = (t[12] == '+') ? '-' : '+';
t = String.Format ("{0}{1}{2}{3}{4}:{5}{6}", century, t.Substring (0, 12), sign,
t[13], t[14], t[15], t[16]);
mask = "yyyyMMddHHmmsszzz";
#if !NET_2_0
utc = false;
#endif
break;
}
#if NET_2_0
return DateTime.ParseExact (t, mask, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
#else
DateTime result = DateTime.ParseExact (t, mask, null);
if (utc)
return result;
return result.ToUniversalTime ();
#endif
}
}