问题描述
1.现在我试图创建一个只包含工作日名称、小时和分钟的 SimpleDateFormat。 我刚刚定义了一个这样的模式: DateFormat sdf = new SimpleDateFormat("EEE:hh:mm");然而,这种模式似乎根本不起作用;
2.这是我定义日期格式的代码,下面的代码只能包含小时和分钟,当我尝试输入“Tue:21:30”时,“Tue”不会被存储。如何定义像““Tue 21:30”这样的时间格式?
description & company
解决方法
java.util.Date
类表示日期与 UTC 时间的组合。
您只有星期几,没有日期。而且您没有偏移量或时区指标。你只有一个需要的部分,一个时间。所以解析"Tue:21:30"
这样的字符串是没有意义的。
另一件事:您正在使用糟糕的日期时间类。这些类在多年前被 JSR 310 中定义的现代 java.time 类取代。
要将星期几与一天中的某个时间配对,请编写一个类。在 Java 16 中,我将使用新的 records 特性来简要地编写这样一个类。编译器隐式创建构造函数、getter、equals
& hashCode
和 toString
。
record DayOfWeekTime ( DayOfWeek dayOfWeek,LocalTime localTime ) {}
用法。
DayOfWeekTime dowTime = new DayOfWeekTime( DayOfWeek.TUESDAY,LocalTime.of( 21,30 ) ) ;
如果您想以这种方式限制数据,或者使用一对 int
值表示小时和分钟,而不是 LocalTime
。我也会添加一个显式构造函数,以验证这些 int
输入的允许值范围。
record DayOfWeekTime ( DayOfWeek dayOfWeek,int hour,int minute ) {}
添加方法以解析和生成所需格式的字符串。
如果需要排序,您可能需要添加一个 compareTo
方法来实现 Comparable
接口。
Date
代表一个瞬间。 “周二晚上 9 点 30 分”不是一个瞬间 - 哪个周二?晚上 9:30 在哪个时区?如果您使用 DateTimeFormatter
,您可以假设这些东西的默认值,但从评论看来,您似乎不想假设任何东西。您只想存储解析的内容。
您可以编写自己的类,表示一周中的某天 + 小时 + 分钟仅。如果您实现 TemporalAccessor
,您将能够使用 DateTimeFormatter
对其进行解析和格式化。下面是一个例子:
final class DayOfWeekLocalTime implements TemporalAccessor {
private final DayOfWeek dow;
private final int hour;
private final int minute;
private DayOfWeekLocalTime(DayOfWeek dow,int minute) {
this.dow = dow;
this.hour = hour;
this.minute = minute;
}
public static DayOfWeekLocalTime of(DayOfWeek dow,int minute) {
return new DayOfWeekLocalTime(dow,hour,minute);
}
public static DayOfWeekLocalTime parse(String s,DateTimeFormatter formatter) {
TemporalAccessor ta = formatter.parse(s);
return new DayOfWeekLocalTime(
DayOfWeek.of(ta.get(ChronoField.DAY_OF_WEEK)),ta.get(ChronoField.HOUR_OF_DAY),ta.get(ChronoField.MINUTE_OF_HOUR)
);
}
@Override
public String toString() {
// a default format
return DateTimeFormatter.ofPattern("EEE:HH:mm").format(this);
}
@Override
public boolean isSupported(TemporalField field) {
return field == ChronoField.DAY_OF_WEEK ||
field.getBaseUnit() == ChronoUnit.HOURS ||
field.getBaseUnit() == ChronoUnit.MINUTES ||
field == ChronoField.AMPM_OF_DAY;
}
@Override
public long getLong(TemporalField field) {
if (!isSupported(field)) {
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
}
if (field == ChronoField.DAY_OF_WEEK) {
return dow.getValue();
}
return field.getFrom(LocalTime.of(hour,minute));
}
// equals and hashcode omitted for brevity
}
解析:
DayOfWeekLocalTime.parse("Tue:21:30",DateTimeFormatter.ofPattern("EEE:HH:mm"));
,
Do not use java.util.date
,因为它有几个消极方面。
使用更新的(自 Java 8 起)JSR 310: Date Time API。
你可以这样做:
DateTimeFormatter format1 = DateTimeFormatter.ofPattern("EEE HH:mm");
DateTimeFormatter format2 = DateTimeFormatter.ofPattern("EEEE HH:mm"); //gives you full name of the day
LocalDateTime ldt = LocalDateTime.now();
//if it's Thursday,10:30
System.out.println(ldt.format(format1)); //prints Thu 10:30
System.out.println(ldt.format(format2)); //prints Thursday 10:30
或者,使用任何其他日期对象代替 LocalDateTime API
中的 .now()
。
可以在here、here、here 和here 中找到有关为什么不使用java.util.date
的其他一些参考资料。