2009-11-16 100 views
0

我的工作再使用.NET编写现有的Java软件解决方案。在一个点上,Java解决方案在一个字符串的开始读取时间标记,只要是这样的:时间戳解析在C#

SimpleDateFormat dateFormat = new SimpleDateFormat(timeFormat); 
dateFormat.setLenient(false); 

try 
{ 
    timeStamp = dateFormat.parse(line); 
} 
catch (ParseException e) 
{ 
    //... 
} 

现在我试图做同样的在C#:

DateTimeFormatInfo dateTimeFormatInfo = new DateTimeFormatInfo(); 
dateTimeFormatInfo.FullDateTimePattern = format; 

try 
{ 
    timeStamp = DateTime.Parse(line, dateTimeFormatInfo); 
} 
catch (FormatException ex) 
{ 
    //... 
} 

两种语言工作直到我在行变量中的时间戳之后添加一些随机文本。 Java会忽略它,但C#在行中的时间戳文本之后将不允许其他任何内容。

因此,尽管Java是幸福的解析 “01/01/01 01:01:01001的Hello World”作为时间戳,C#不是,因为“Hello World!”未在格式字符串中指定。

然而,正如我不能做什么可能来我的琴弦里面的时间戳之后的任何说法,我不能将其包含在我的格式字符串。

任何想法?

预先感谢您。

+0

你能保证的日期格式将永远是文件中的一样吗?只需取该行的前N个字符并解析该字符。 – 2009-11-16 14:21:31

+0

我可以保证日期格式是相同的,但是,您的解决方案不考虑日期格式,例如“2009年5月1日”。长度可能会大不相同。 – Callash 2009-11-16 14:24:00

+0

不是你的问题的答案,但如果可能的话,你应该使用DateTime.TryParse而不是try ... DateTime.Parse ... catch。 http://msdn.microsoft.com/en-us/library/system.datetime.tryparse.aspx – LukeH 2009-11-16 14:25:27

回答

1

如果你知道你的日期会在什么样的格式,并与它的存储上下文那么这是一个优势。

举例来说,如果你知道你是存储昨天的日志或类似的东西:

DateTime yesterday = DateTime.Today.AddDays(-1); 
timestamp = DateTime.Parse(
    line.SubString(0, line.IndexOf(yesterday.Year.ToString()) + 4)); 

编辑:有没有什么日期(甚至有一个空格)后划定的文本?

如果有,你可以做这样的事情:

private static DateTime GetDate(string line) 
{ 
    int index = 0; 
    DateTime theDate; 
    string s = line; 

    while(!DateTime.TryParse(s, out theDate)) 
    { 
     index = line.IndexOf(" ", index); 
     s = line.Substring(0, index); 
    } 

    return theDate; 
} 

注意:这将无法得到时候如果有日期后的文本(因为它能够解析出的日期不搜索时成功)。您可以通过从行尾开始获取空格索引并向后移动来解决这个问题。我会把它留给你。

+0

不幸的是,我不这样做。时间格式模式由配置给出,但日期可能是昨天,一个月前,一年前的任何事情。 – Callash 2009-11-16 14:23:00

0

看起来.NET是要分析整个字符串,你不控制整个字符串。我会说使用TryParse(),如果失败,剥离字符串中最右边的“单词”,然后重试。我对Java并不熟悉,但它可能会在下面做到。

2

试试这个:

Dictionary<string, string> tests = new Dictionary<string,string>() 
{ 
    { "yy/MM/dd HH:mm:ss,fff", "01/01/01 01:01:01,001 Hello World!"}, 
    { "yyyyMMddHHmmssfff", "2009111615413829403 Hello World!"}, 
    { "d.M.yyyy H:m:s,fff", "8.10.2009 8:17:26,338 Hello World!" } 
}; 

foreach(KeyValuePair<string, string> test in tests) 
{ 
    string pattern = test.Key; 
    string format = test.Value; 

    DateTimeFormatInfo dateTimeFormatInfo = new DateTimeFormatInfo(); 
    dateTimeFormatInfo.FullDateTimePattern = pattern; 

    Console.WriteLine("{0} - {1}", pattern, format); 
    DateTime timeStamp = DateTime.MinValue; 
    if (pattern.Contains(' ')) // approach 1: split and conquer 
    { 
     format = String.Join(" ", format 
      .Split(" ".ToCharArray()) 
      .Take(pattern.Count(c => c == ' ') + 1)); 
    } 
    else 
    { 
     format = format.Substring(0, pattern.Length); 
    } 


    if (!DateTime.TryParseExact(
     format, pattern, dateTimeFormatInfo, 
     DateTimeStyles.AllowWhiteSpaces, out timeStamp)) 
    { 
     Console.WriteLine("\tSomething sad happened"); 
    } 
    else 
    { 
     Console.WriteLine("\t{0}", timeStamp.ToString(pattern)); 
    } 
} 
Console.Read(); 

注意我不使用DateTime.Parse,因为它抛出一个异常,如果字符串不是有效DateTime格式化字符串。

UPDATE 1:更好的输入处理,如不期望的空白,但使用模式长度

UPDATE 2:两个先前方法合并到此的代码;我知道在测试#2中使用一个d,但我认为我们不能对此做任何事情。

+0

去那里,但如果我看到它正确,这假定在时间戳后总是有一个空白。我可能遇到的一行代码如下所示:“2009111615413829403”,即“yyyyMMddHHmmssfff”后跟两位数的错误代码。 – Callash 2009-11-16 14:42:06

+0

仍然不是,因为您的解决方案期望时间模式和时间戳具有相同的长度。我的模式可能是“d.M.yyyy H:m:s,fff”(长度为18),解析的时间戳可能是“8.10.2009 8:17:26,338”(长度为21)。 – Callash 2009-11-16 15:08:18

+0

你是对的;该模式总是有效的? – 2009-11-16 15:22:30