2013-01-02 26 views
16

我得到两个日期为字符串值进行比较的日期,我想检查开始时间比结束时间早。我对它们进行比较,因为它是不使用SimpleDateFormat它们转换为日期,就像这样:在字符串格式

String startTime = "2013-01-02 14:25:56"; 
String endTime = "2013-01-02 14:30:56"; 

if(endTime.compareTo(startTime) > 0){ 
    System.out.println("End time is greater than start time"); 
} 

真的有必要将它们转换为日期比较?我会错过任何东西吗?我做对了吗?

+7

yyyy-mm-dd格式很好,因为如果你排序这些类型的值,你会得到正确的值,如果你有mm.dd.yyyy或dd.mm.yyyy,你会得到错误的结果......在乍一看,这一切都OK –

+2

如果你一定会得到这种格式,那么你很安全... –

+4

值得注意的是,为什么这个工作方式你有这些字符串:[字典排序](http:///en.wikipedia.org/wiki/Lexicographical_order) –

回答

9

真的有必要将它们转换为日期比较?

如果您不必包含时区,并且可以确保始终使用此格式,则词法顺序将起作用。

我会想什么?

你失去灵活性

我做了正确的事情?

那要看的观点。我在专门的搜索工具中使用类似的东西(仅出于性能原因)。通常我转换为日期并比较这些对象。

17

你将丢失是验证,如果日期是在事实上格式正确。

如果日期格式化为正好是正如您每次显示的那样,那么这将起作用。如果有可能会有所不同,那么解析和比较产生的Date对象将至少增加一些检查。

例如,如果两个日期的一个碰巧被格式化为2013.01.02 14:30:56或者甚至包括一个未格式化的日期,例如yesterday那么您的代码会默默地承担了部分的顺序(即最有可能没有什么实际订单)并继续。它应该应该做的是通知用户(或日志文件,...)某些期望没有得到满足。

+3

好点。如果比较“2013-01-01 08:42:42”和“2013-01-01 8:42:42”,并期望它们相等,则与字符串比较的另一个更细微的区别可能是。 – Alderath

+1

@Alderath:是的,这正是我写作时写的“正如你所展示的那样格式化*”。如果格式中有*任何*的变化,那么解析是更安全的选择(正如我暗示的那样:除非有非常好的理由,否则我会在任何情况下解析+比较)。 –

+0

是的。抱歉。我不是故意暗示我发现了你没有的东西。我只是举出另一个日期如何不同的例子。与此不同的是,如果用户被提示输入并且“2013-01-02 14:25:56”被用作日期应该具有的格式的示例,则不管前导零是否是只需要一个数字就可以工作数小时。 (但我猜测OP给比较方法的输入不是用户输入,因为如果是的话,它肯定需要验证) – Alderath

1

我建议他们转换为日期首先是一个小更安全,但只要你确定的格式(或时区,等...)永远不会改变你,然后一个日期比较和对比该格式的字符串应该始终等同。

1

是的,最好将字符串转换为日期并进行比较。

  1. 它确保它们实际上是有效的日期,所以没有20-20-2012。
  2. 转换完成后,只剩下一个数字比较。
  3. 当比较不同格式的日期时,它具有很大的灵活性。
  4. 另一种方法是编写解析每个数字并将其与另一个数字进行比较的代码,这同样适用。
2

怎么样

"999-01-01 00:00:00" 

"10000-01-01 00:00:00" 
+0

很好的例子,但这打破了保持相同日期格式的全部观点,为了正确比较,我们应该将10000与00999进行比较,并得到一个好的结果,否则精度将会失败 –

7

您可以比较的日期时间不正确解析它当且仅当这3个条件:

  1. 日期时间总是在同一格式:

    • 相同数量的字段
    • 这些字段必须是纯数字。 (字符串比较:Jan>April,Wed>Thu)。
    • 字段的大小是固定的(如果需要,填充0)。例如,没有适当的填充将导致10:01 < 1:01:具有比数字更大的ASCII码)。
    • 非数字部分(包括分隔符)必须与间距相同。
  2. 该字段按单位的大小降序排列(较大的单位向右,较小的单位向左)。例如:YEAR-MONTH-DAY HOUR:MINUTE:SECOND.MILISECOND

  3. 它们必须在同一时区。时区信息(如果存在)应该具有相同的表示(SGTUTC+8当前是等效的,但字符串比较不会知道这一点)。需要注意的是,上述暧昧条件“同一时区”就够了比较平等的,但比较大/小,必须有被比较时区2日期间发生的事情没有任何变化。

+0

+1。我想你可以说iif。 – assylias

+0

提及时区+1。我多么恨他们。 – f1sh

8

这是不好的做法和代码的气味。

您失去了语义正确和可读的代码。 (和可扩展性,时区,和其他的正确的事情,已经已经说过)

你不想比较两个String S,你要比较2 Date秒 - 所以只是这样做,比较两个Date对象。

如果您创建单元测试并测试比较方法,则永远不会编写一种方法,在每种情况下都能正确比较2个“字符串”日期,而无需将它们转换为日期。

+1

我必须同意这个答案最重要的。比较作为字符串是一种脆弱的软件方法。是的,你可以仔细地确定它的工作条件,但它很可能在未来的某个时间点以一种非常难以找到的方式失败。你根本无法保证将来会改变什么或不改变什么。 – dashrb

+1

+1用于提出代码语义。我们经常听到“它有效,所以没关系”,但是如果代码遵循语义,你不会轻易陷入陷阱。 – Javier

0

我的日期来自基于字符串的来源,并且始终格式为YYYY-MM-DD,没有时区信息或其他复杂情况。因此,当比较一长串日期时,将它们作为字符串进行比较比将它们首先转换为日期对象更简单且更高效。

这从来就不是一个问题,直到我犯了这个错误在我的代码:

boolean past = (dateStart.compareTo(now) == -1); 

这是给一些不正确的结果,因为它的compareTo不仅返回值-1,0或1。这是简单的修正:

boolean past = (dateStart.compareTo(now) < 0); 

我包括因为这是试图找出我在做什么错了,当我发现如此的一个问题在这里,这的疑难杂症。