在Java中区分和解析日期

3
我知道这个话题并不新鲜,但我必须再次挖掘它。我已经多次搜索了网络(包括一些Stackoverflow上的主题),但到目前为止都没有找到令人满意的答案。
(其中之一是我检查的Java中解析模糊日期优雅地处理多种日期格式
我正在用Java编写一个日期解析器,它接受一个日期并生成一个格式字符串,该字符串可供SimpleDateFormat用于解析日期。
日期通过正则表达式(是的,它很丑陋)从日志文件(IBM Websphere、Tomcat、Microsoft Exchange等)中解析。因为我们有至少两个不同位置的客户,所以不能简单地将字符串扔到SimpleDateFormat的解析方法中,并期望它能正常工作。
此外,还存在日期和月份位置的问题(即格式“dd/MM/yyyy”或“MM/dd/yyyy”),如果没有至少两个数据集,其中日期数字已更改,则无法解决。
因此,我的当前方法是将特定客户系统上安装的特定软件的日期格式存储在数据库(mysql/xml/...)中,并强制用户至少指定客户名称和软件名称,以便有足够的上下文来分解可能性的数量格式可以给出。
然后,将使用此“子集”尝试解析指定软件的日志文件。 (子集以HashMap中HashMap的形式存储, Integer键是格式字符串的长度,第二个HashMap的String键指定仅包含分隔字符的日期签名。 (例如,“.. ::。”表示格式为“dd.MM.yyyy 11:11:11.111”的日期))
我还考虑数字的值,即数字>12必须是一天,因为没有第13个月。但是,这仅对大于每月12日的日期字符串有效。
是否有任何机会避免实现关于日志文件环境的先前知识,从而使解析器能够可靠地解析一个日期,而无需参考第二个日期字符串进行比较?
我已经卡住了将近3个月了-。-
任何建议都非常受欢迎=)
编辑:

好的,各位,这个帖子可以关闭了。我现在想出了一个不同的解决方案来解决我的特定问题。对于那些感兴趣的人: 我正在用Java编写一个日志阅读器。由于我们有定期维护,我必须读取许多日志文件。 但是文件中写入的不仅仅是纯文本信息。 想象一下,服务器刚刚崩溃了,现在是星期天晚上,下一个注意到这一点的人是客户的IT部门负责人。然后在第二天进行维护并检查日志文件。从内容上来看,一切似乎都很好,没有什么异常。在发送维护报告半个小时之后,我收到了一封电子邮件,上面提到的IT部门负责人发牢骚,说服务器已经崩溃了,似乎没人注意到。

问题是,你无法跟踪具有数千行的日志文件的内容和时间戳。因此,我开发了一个组件,它读取日志文件并计算两个不同日志条目之间的时间。每个日志行都被解析为java.util.Date,以便稍后获取日期作为时间戳,以实现日志间隔的高分辨率。然后将差异投射到一条线图上,使两个日志行之间的较长超时作为与文件其余部分相关的大峰值可见。

我现在的解决方案是完全丢弃字符串的日期部分,并插入一个具有预定义格式的虚拟日期。只有当小时和分钟接近23:59时,日期才会更改。 原始日期稍后将在"假数据"下面呈现在图表上。

我感谢你们所有人的建议和反馈=) (希望我的英语到目前为止已经可以理解了;))


......一个数字大于12的必须是一个日期,因为没有第13个月。- 我不想打击你的兴致,但在某些日历中确实有第13个月。http://en.wikipedia.org/wiki/Undecimber - gustafc
我个人不太喜欢使用这样的“公理”(即规则说“数字>12=日”),但对于这个规则,我可以保证给定的数据始终以12为月份位置的最高值来表达。 (顺便问一下,Java会如何处理第13个月呢?之前进行的快速测试结果是在没有给出格式字符串的情况下,“03.13.2011”被解释为2012年1月3日) - salgmachine
仅供参考,日志文件是如何传输给您的?它们都是一些硬日志(文件)通过某种方式发送给您吗?(还是您从网络驱动器上获取它们...或者其他途径?) - Jasoon
既然我们需要维护应用程序部署的系统,通常我会通过 RDP 连接下载它们。通常,每台服务器都有一个以上的日志文件要传输,而父目录只是打包成一个 zip 文件。我已经想到使用“文件最后更改”时间戳(在Java中可通过java.io.File.lastModified()访问)来获取更多上下文信息,但对于低变化率、包含数个月日志数据的日志来说,这并不适用。 - salgmachine
但是最后修改日期不会与日志文件中的最后条目相匹配吗?即使在一年中月份和日期相同的12天里无法使用,至少也能为你提供更多的信息。 - Jasoon
显示剩余2条评论
3个回答

1

我的建议是将所有日期存储为“不确定的”,直到可以解决歧义为止。(这假设特定客户始终以相同格式提供数据。)一旦您从客户那里获得了一个日志,您就能够明确识别日期格式,然后可以回溯地将此格式应用于以前的文件。

为此,您需要一个表格,将每个客户映射到其日期格式,并使用某个标记(例如NULL)表示该格式尚未确定。您还可能需要创建自己的日期表示形式,以便您可以对这些不确定的日期进行建模。

因此,举个例子,如果可能的日期格式为:

dd/mm/yyyy
mm/dd/yyyy
yyyy/mm/dd
yyyy/dd/mm

给定日期,您应该总是能够确定年份(允许使用两位数的年份将使这个问题变得更加困难)。因此,您应该能够按照以下方式映射日期:

25/01/2011 -> UNAMBIGUOUS_DD_MM_YYYY
12/01/2011 -> AMBIGUOUS_XX_XX_YYYY
2011/03/03 -> AMBIGUOUS_YYYY_XX_XX
03/30/2011 -> UNAMBIGUOUS_MM_DD_YYYY

幸运的是,日期的格式字符串不会改变,因为我们对大多数客户系统具有行政主权,我们的应用程序已经部署在这些系统上。(我的公司基于IBM WebSphere生产门户解决方案)至于歧义,我已经在当前解决方案中实现了它。(当前的方法是读取整个日志文件,解析所有日期并尽可能地格式化它们。然后,在第二个“清理”轮中比较部分格式化的字符串...) - salgmachine

0
如果可能的话,您可以要求客户在传递实际日期字符串的同时也传递日期格式字符串。
例如,在他们的日志文件中,他们需要有另外一列
.....,'03/11/2011','MM/DD/YYYY',...

哎呀,不幸的是,这个解决方案并不适用,因为每个应用程序都必须被修改,而有些情况下这是不可能的(例如在处理Exchange Server日志时...) - salgmachine

0

我认为你正在采用的策略(即分析更大的数据集)是最好的选择。 从单行日志中,你永远不会知道3/5/11是2011年5月3日还是2011年3月5日。(我猜也许有一些地区可能会将其解释为2003年5月11日...) 我自己曾经遇到过这些问题,我只能尝试通过查看大于12的数字或者变化最快的内容(必须是“天”)来引入某种上下文。但你已经自己提到了这一点...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接