日期格式更改

6
如果输入为01-01-2015,它应该更改为2015-01-01
如果输入为2015-01-01,它应该更改为01-01-2015
我使用了SimpleDateFormat,但没有得到正确的输出结果:
//Class to change date dd-MM-yyyy to yyyy-MM-dd and vice versa
public class ChangeDate {
  static SimpleDateFormat formatY = new SimpleDateFormat("yyyy-MM-dd");
  static SimpleDateFormat formatD = new SimpleDateFormat("dd-MM-yyyy");

  //This function change dd-MM-yyyy to yyyy-MM-dd
  public static String changeDtoY(String date) {
    try {
      return formatY.format(formatD.parse(date));
    }
    catch(Exception e) {
      return null;
    }
  }

  //This function change yyyy-MM-dd to dd-MM-yyyy
  public static String changeYtoD(String date) {
    try {
      return formatD.format(formatY.parse(date));
    }
    catch(Exception e) {
      return null;
    }
  }
}

我希望有一个自动检测日期格式并转换为其他格式的条件。

第一个连字符的位置可能在哪里? - Henry
1
根据选择函数获取第一个连字符出现的位置 - Sreemat
5个回答

7

有两个选择:

  1. Try to check with regular expression sth. like:

    if (dateString.matches("\\d{4}-\\d{2}-\\d{2}")) {
        ...
    }
    
  2. Try to convert to first pattern, if it throws exception, try to convert to another pattern (but it is bad practice to do so)


我会尝试第一种选项。我已经尝试了第二种选项,但它转换并给出了不合适的日期。谢谢。 - Sreemat
使用异常处理应该局限于实际的异常情况,而不是作为处理意图行为的方式。-1. - CosmicGiant
它不会抛出异常 @AlmightyR - Sreemat
@Sreemat,我没有说它的确如此。第二种方法使用异常来实现正常、预期的行为。这是不好的做法。这就是(一半)答案差劲的原因。一旦移除了那个糟糕的方法,-1 的得分将会被取消。 - CosmicGiant

2

正则表达式过于复杂

对于日期时间处理,不需要使用正则表达式

只需尝试使用一种格式进行解析,并捕获预期的异常。如果确实抛出了异常,则尝试使用另一种格式进行解析。如果抛出异常,则说明输入既不符合第一种格式也不符合第二种格式。

java.time

您现在正在使用旧的麻烦日期时间类,这些类已被Java 8及更高版本内置的java.time框架所取代。新类受到广受欢迎的Joda-Time框架的启发,旨在成为其继承者,概念类似但重新架构。由JSR 310定义。由ThreeTen-Extra项目扩展。请参见Oracle教程

LocalDate

新类包括一个只有日期而没有时间的类LocalDate。正是您所需要的。

格式化程序

您的第一个格式可能是标准的ISO 8601格式,即YYYY-MM-DD。此格式默认在java.time中使用。

如果第一次解析尝试失败,因为输入与ISO 8601格式不匹配,则会抛出DateTimeParseException异常。

LocalDate localDate = null;  
try {
    localDate = LocalDate.parse( input );  // ISO 8601 formatter used implicitly.
} catch ( DateTimeParseException e ) {
    // Exception means the input is not in ISO 8601 format.
}

另一种格式必须由类似于使用SimpleDateFormat的编码模式指定。因此,如果我们从第一次尝试捕获异常,则进行第二次解析尝试。
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "MM-dd-yyyy" );
LocalDate localDate = null;  
try {
    localDate = LocalDate.parse( input );
} catch ( DateTimeParseException e ) {
    // Exception means the input is not in ISO 8601 format.
    // Try the other expected format.
    try {
        localDate = LocalDate.parse( input , formatter );
    } catch ( DateTimeParseException e ) {
        // FIXME: Unexpected input fit neither of our expected patterns.
    }
}

1
使用异常来处理非异常行为(/用于流程控制)是非常糟糕的做法。-1。 - CosmicGiant
1
这里需要进行异常处理,因为核心Java方法声明了异常。如果省略try/catch,代码将无法成功编译。此示例捕获由解析方法抛出的特定DateTimeParseException,而不是普通的Exception或Throwable,因此该示例显示了简洁和正确的代码。 - Jason Plurad
@JasonPlurad 嗯,DateTimeParseException是一个RuntimeException,因此编译器不需要显式的异常处理(throws或catch)。或者你说的是其他什么?无论如何,LocalDate.parse(...)将在没有try/catch - 代码的情况下编译。然而,这个解决方案是否优雅是另一个问题。 - Meno Hochschild
啊,是的,你说得对。这是一个RuntimeException。如果一个方法明确地声明了一个RuntimeException的throw,即使它没有编译错误,我仍然会用try/catch块将其包围起来。谢谢。 - Jason Plurad
@JasonPlurad 我对不良实践的评论是指“如果确实抛出异常,请尝试使用另一种格式进行解析。” - CosmicGiant
@JasonPlurad:“这个例子捕获了由解析方法抛出的特定DateTimeParseException,而不是普通的Exception或Throwable(...)” - 这与我的批评无关。•••“(...)因此,这个例子展示了简洁和正确的代码。” - 简洁?是的。正确?不是 - CosmicGiant

0

了解模式, 匹配器正则表达式

Java代码(基于OP):

if (date.matches("\\d{2}-\\d{2}-\\d{4}")){
  //convert D format to Y format...
} else if(date.matches("\\d{4}-\\d{2}-\\d{2}")){
  //convert Y to D...
} else {
  throw new IllegalArgumentException("Received date format is not recognized.");
}

注意:这个匹配模式可以通过使用“捕获组”进行改进。
例如:"\\d{4}(-\\d{2}){2}""(-?\\d{2}){2}\\d{4}"

0

请参见:https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/datetime/iso/examples/StringConverter.java

非 ISO 日期转换 https://docs.oracle.com/javase/tutorial/datetime/iso/nonIso.html

添加一个新的年表来标识 ISO 日期是另一种兼容(不会出错)的输入日期数据并将其存储在正确的结构中(其他函数可以轻松操作数据)。请参见:https://docs.oracle.com/javase/8/docs/api/java/time/chrono/Chronology.html

'正则表达式方法' 可能会因错误输入而被破坏,并且没有办法返回标准错误以响应任何输入(以在任何地方获得标准相同的结果)。

请查看用户“Tardate”在此线程中提供的答案:如何在Java中对日期进行健全性检查
您希望获得防弹输入并将其存储在正确识别的结构中,以便轻松地通过其他功能进行操作。

-2

只需比较日期字符串中第一个“-”字符的位置即可。


1
假设读者知道或理解“如何”,此时他们可能不会询问/阅读此答案。-1。 - CosmicGiant
@SantoshVishwakarma 目前来看,这个回答应该作为评论发布。请添加更多的解释和示例代码,以成为一个完整的回答。 - Basil Bourque

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