在 Java 中获取包含允许的文件名字符的完整语言环境日期和小时字符串的好方法是什么?

What would be a good way to get a full locale date and hour string with allowed filename characters, in Java?

我想构建一个包含语言环境日期和小时的字符串,连接起来,它必须是人类可读的并且与最常见的 OS 文件允许的字符兼容。类似于:

6-23-20_03-06-50

我将其用作用户的自动文件名建议。 为此,我编写了以下代码:

public class CustomDateProvider {

    private static final String TWO_DIGIT_PATTERN = "%02d";

    public static String getDashedDateAndHourFromDate(Date date) {
        ZonedDateTime dateTime = date.toInstant().atZone(ZoneId.systemDefault());
        int hour = dateTime.getHour();
        int minute = dateTime.getMinute();
        int second = dateTime.getSecond();

        DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.getDefault());
        String localeDate = dateFormat.format(date);
        String dashedDate = localeDate.replace("/", "-");

        return dashedDate
                + "_"
                + String.format(TWO_DIGIT_PATTERN, hour)
                + "-"
                + String.format(TWO_DIGIT_PATTERN, minute)
                + "-"
                + String.format(TWO_DIGIT_PATTERN, second);
    }
}

因此,我假设日期分隔符字符将始终为“/”,我不确定这是否始终正确。 无论哪种方式,可能有更好的方法来实现我的目标,如果有任何改进,我将不胜感激。

这是获取语言环境的方法Date_Time-

import java.time.LocalDateTime;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

public class CurrentDateTimeExample {
   public static void main(String[] args) {
       LocalDateTime currentDateTime = LocalDateTime.now();
       System.out.println("Current Date and Time: "+currentDateTime);

       DateTimeFormatter pattern = DateTimeFormatter.ofPattern("uuuu-MM-dd_hh-mm-ss");
       System.out.println("Date Time in 12 Hour format - " + currentDateTime.format(pattern));
   }
}

更多详情请看这里Get Locale Date_Time

java.time

你使用的是可怕的日期时间类,几年前被现代java.time类.

避免本地化格式

您要求以各种本地化格式表示日期时间值的文本。这种方法在文件名中是不明智的。

  • 本地化格式很可能包含在各种文件系统上会出现问题的字符。您使用斜杠字符的示例 MM/dd/yyyy 格式可能会导致某些面向 Unix/POSIX 的文件系统出现问题。
  • 本地化格式可能会被习惯不同的人误解。
  • 本地化格式可能会使将该字符串解析回日期时间值变得困难或不可能。

相反,我强烈建议仅使用标准 ISO 8601 格式。

ISO 8601 的“基本”变体

您要求:

must be human readable and compatible

我建议坚持使用 ISO 8601 格式的“基本”变体,它最少使用分隔符。为了与各种文件系统兼容,您希望避免使用斜杠、反斜杠、冒号和 space 字符。

ISO 8601 格式按重要性顺序排列:年、月、日、时、分、秒、小数秒。大写 T 将日期部分与时间部分分开。此类字符串按时间顺序按字母顺序排序。

UTC

我还建议您坚持使用 UTC(零小时-分钟-秒的偏移量)。为此,使用 Instant(或 OffsetDateTime 设置为 UTC)。

Instant instant = Instant.now() ; // Capture current moment as seen in UTC.

如果您不需要小数秒或分钟,请截断。

Instant instant = Instant.now().truncatedTo( ChronoUnit.MINUTES ) ;

您将执行字符串操作以删除年-月-日之间的连字符和时-分-秒之间的冒号。

String output = instant.replace( "-" , "" ).replace( ":" , "" ) ;

对于 2021-01-23T12:30:35Z 那将是:

20210123T123035Z

结尾的Z表示UTC,发音为“Zulu”。

划片刻

如果您坚持使用特定时区的日期时间,请使用 ZonedDateTime

ZoneId z = ZoneId.systemDefault() ;  // Or ZoneId.of( "Africa/Tunis" ) and such.
ZonedDateTime zdt = ZonedDateTime.now().truncatedTo( ChronoUnit.MINUTES ) ;

指定格式模式。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmss" ) ;
String output = zdt.format( f ) ;

示例:

20210123T123035

我不建议省略区域或偏移量,但如果您坚持,就可以了。

如果您坚持 6-23-20_03-06-50 的示例格式,请定义一个 DateTimeFormatter 来匹配。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "M-d-uu'_'HH-mm-ss" ) ;

允许单位数的月份或日期是我反对的另一件事。就像使用两位数的年份一样。



关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类。 Hibernate 5 和 JPA 2.2 支持 java.time.

在哪里获取java.time类?