无法在C#中解析Oracle时间戳
我有Oracle的时间戳:
string timestamp = "23-JUN-14 09.39.04.000000000 AM";
我无法将其解析为系统日期时间对象。 我用了:
CultureInfo provider = CultureInfo.InvariantCulture; String format = "yy-MMM-dd hh:mm:ss:fffffff"; string timestamp = "10-DEC-07 10.32.47.797201123 AM"; { var date = DateTime.ParseExact(timestamp, format, provider); DateTime dateTime = DateTime.ParseExact(timestamp.ToString(), "dd-MMM-y HH:mm:ss", CultureInfo.InvariantCulture); }
它仍然传递错误。 它在m后工作7 f但不超过。 我用过Parse
尝试ParseExact
– 有什么办法吗?
根据https://stackoverflow.com/a/23198962/328864 ,没有办法跳过精确模式的部分,所以我猜你可以这样做:
CultureInfo provider = CultureInfo.InvariantCulture; string timestamp = "10-DEC-07 10.32.47.797201123 AM"; String format = String.Format("yy-MMM-dd hh.mm.ss.fffffff{0} tt", timestamp.Substring(26,2)); DateTime date = DateTime.ParseExact(timestamp, format, provider); Console.WriteLine(date);
虽然不是很漂亮。
.NET DateTime结构的精度为tick – 100纳秒 – 0.0000001秒 – 点后7位小数。
Oracle TimeStamp的精度高达纳秒 – 0.000000001 – 点后9位小数。
这就是标准DateTime无法存储所有可能的oracle TimeStamps的原因。 并且它的解析函数在TimeStamp的更精确的字符串表示中失败。
那么,可以尝试什么:
- 将查询中的TimeStamps格式化为DataTime可解析的某种格式(必要时会丢失精度) – http://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements004.htm
- 或者创建自己更精确的
CustomTimeStamp
.Net结构并手动解析
一旦我们开始使用ODP.NET,我们必须实现如下的扩展:
public static T ConvertOracleValue(this object value) { if (value != null) { Type typeOfValue = value.GetType(); if (typeOfValue.Namespace.Contains("Oracle.DataAccess")) { if (typeOfValue.Name.Equals("OracleTimeStamp")) { int tempInt = 0; Oracle.DataAccess.Types.OracleTimeStamp ots = (Oracle.DataAccess.Types.OracleTimeStamp)value; tempInt = Int32.TryParse(ots.Millisecond.ToString("000").Substring(0, 3), out tempInt) ? tempInt : 0; DateTime ret = new DateTime(ots.Year, ots.Month, ots.Day, ots.Hour, ots.Minute, ots.Second, tempInt); return ConvertHelper.ConvertValue (ret); } if (typeOfValue.Name.Equals("OracleTimeStampLTZ")) { int tempInt = 0; Oracle.DataAccess.Types.OracleTimeStampLTZ ots = (Oracle.DataAccess.Types.OracleTimeStampLTZ)value; tempInt = Int32.TryParse(ots.Millisecond.ToString("000").Substring(0, 3), out tempInt) ? tempInt : 0; DateTime ret = new DateTime(ots.Year, ots.Month, ots.Day, ots.Hour, ots.Minute, ots.Second, tempInt); return ConvertHelper.ConvertValue (ret); } if (typeOfValue.Name.Equals("OracleTimeStampTZ")) { int tempInt = 0; Oracle.DataAccess.Types.OracleTimeStampTZ ots = (Oracle.DataAccess.Types.OracleTimeStampTZ)value; tempInt = Int32.TryParse(ots.Millisecond.ToString("000").Substring(0, 3), out tempInt) ? tempInt : 0; DateTime ret = new DateTime(ots.Year, ots.Month, ots.Day, ots.Hour, ots.Minute, ots.Second, tempInt); return ConvertHelper.ConvertValue (ret); } string temp = value.ToString(); return ConvertHelper.ConvertValue (temp); } } else { return default(T); } return ConvertHelper.ConvertValue (value); }
其中ConvertHelper.ConvertValue是另一个扩展:
public static class ConvertHelper { public static T ConvertValue(object value) { Type typeOfT = typeof(T); if (typeOfT.BaseType != null && typeOfT.BaseType.ToString() == "System.Enum") { return (T)Enum.Parse(typeOfT, Convert.ToString(value)); } if ((value == null || value == Convert.DBNull) && (typeOfT.IsValueType)) { return default(T); } if (value is IConvertible) { return (T)Convert.ChangeType(value, typeOfT, new CultureInfo("en-GB")); } return (T)Convert.ChangeType(value, typeOfT); } }
这在我们的测试,集成和生产环境中起到了很大的作用。