在 Java.util.Date 和我自己的日期 class 之间转换时数字会发生变化
Numbers change when converting between Java.util.Date and my own date class
对于预订监控系统,我使用了一个简单的日期 class(未显示完整 class):
package DataBase;
public class Date {
private int day;
private int month;
private int year;
public Date(int day, int month, int year) {
super();
this.day = day;
this.month = month;
this.year = year;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
@Override
public String toString() {
return "Date [day=" + day + ", month=" + month + ", year=" + year + "]";
}
}
我使用这个 class 是因为当我需要处理预订并将它们放入 JTables 时,它简化了我的很多代码。
我从 JDatePicker 获取日期,然后将其与有关预订的更多信息一起放入 SQL 数据库中。然后,当应用程序重新启动时,来自 table 的行用于可视化 JTables。
然而,我的问题是,在将日期从我从数据库中获取的 Java.util.Date
转换为上面我自己的日期 class 时,我遇到了奇怪的行为。我使用这段代码来转换它们:
//Java Util Date, dateString is a string formatted like this: dd-MM-yyyy
Date date = new Date();
DateFormat format = new SimpleDateFormat("dd-MM-yyyy");
date = format.parse(dateString);
//my own date
DataBase.Date dateTemp = new DataBase.Date(date.getDay(),date.getMonth() ,date.getYear());
当我打印 dateString
& dateTemp.toString()
时,我得到以下输出:
19-03-2017
Date [day=0, month=2, year=117]
上面的日期是正确的,但第二行的日月年值不匹配。
另一个例子:
21-03-2017
Date [day=2, month=2, year=117]
它似乎有一个模式,但我似乎无法找到我在这里做错了什么!
您使用的 Date
方法根据计算机的时区设置给出日期,而 class 在内部存储 UTC 时区日期的午夜(0:00 小时)。如果您的时区在 UTC 以东(就像我的一样),那么您很幸运,日期是一致的;如果您 运行 在 UTC 以西的计算机上使用相同的代码,您将获得之前的日期。您绝对不希望您的代码如此脆弱。
除了:SimpleDateFormat
也使用了您计算机的时区设置,因此使用您发布的代码不会发现任何问题;但是你会从你的数据库中得到一个日期。
JB Nizet 在评论中提到这些方法已弃用。它们之所以被弃用,正是因为它们给了你如此脆弱的代码。
有两种解决方法:
- the
Date
documentation 提到你的可怜人,Calendar
class。
- 好的:
java.time.LocalDate
class 在 Java 8 中引入,也被移植回 Java 6 和 7。
让我们先拿好的:
LocalDate local = date.toInstant().atOffset(ZoneOffset.UTC).toLocalDate();
要对此进行测试,您可以使用这种方式生成与来自数据库的日期相等的日期:
date = Date.from(LocalDate.of(2017, 3, 19).atStartOfDay().atOffset(ZoneOffset.UTC).toInstant());
LocalDate
class 提供方法 getDayOfMonth()
、getMonth()
、getYear()
和许多其他方法,它们会给您预期的结果。我强烈希望您会发现这个 class 非常有吸引力,以至于您不需要自己的约会对象 class。如果要更改每个字段,可以使用 withDayOfMonth
、withMonth
和 withYear
方法。请注意,这些 return 新 LocalDate
对象具有新日期,而不是修改现有对象。 LocalDate
实例是不可变的。
如果您不能使用 Java 8 并且不想采用 Eugen Pechanec 在评论中提到的 ThreeTen Backport,您可以求助于 Calendar
class 中介绍的Java 1.1(那是很久以前的事了)。
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTime(date);
DataBase.Date dateTemp = new DataBase.Date(cal.get(Calendar.DAY_OF_MONTH),
cal.get(Calendar.MONTH) + 1, cal.get(Calendar.YEAR));
要使用等于来自您数据库的日期进行测试:
DateFormat format = new SimpleDateFormat("dd-MM-yyyy");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = format.parse(dateString);
我在 cal.get(Calendar.MONTH)
上加 1,因为 Calendar
的月份是从 0 开始的,而你想要一个从 1 开始的日期。
同样,您可以考虑使用 Calendar
而不是您自己的 class。它的 set
方法非常强大,以备不时之需。
为了完整起见,您得到的输出与 Date
class 的文档所说的完全一致。如果您想了解发生了什么(我希望如此),请参阅其 getDay, getMonth and getYear methods. And getDate().
的文档
对于预订监控系统,我使用了一个简单的日期 class(未显示完整 class):
package DataBase;
public class Date {
private int day;
private int month;
private int year;
public Date(int day, int month, int year) {
super();
this.day = day;
this.month = month;
this.year = year;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
@Override
public String toString() {
return "Date [day=" + day + ", month=" + month + ", year=" + year + "]";
}
}
我使用这个 class 是因为当我需要处理预订并将它们放入 JTables 时,它简化了我的很多代码。
我从 JDatePicker 获取日期,然后将其与有关预订的更多信息一起放入 SQL 数据库中。然后,当应用程序重新启动时,来自 table 的行用于可视化 JTables。
然而,我的问题是,在将日期从我从数据库中获取的 Java.util.Date
转换为上面我自己的日期 class 时,我遇到了奇怪的行为。我使用这段代码来转换它们:
//Java Util Date, dateString is a string formatted like this: dd-MM-yyyy
Date date = new Date();
DateFormat format = new SimpleDateFormat("dd-MM-yyyy");
date = format.parse(dateString);
//my own date
DataBase.Date dateTemp = new DataBase.Date(date.getDay(),date.getMonth() ,date.getYear());
当我打印 dateString
& dateTemp.toString()
时,我得到以下输出:
19-03-2017
Date [day=0, month=2, year=117]
上面的日期是正确的,但第二行的日月年值不匹配。
另一个例子:
21-03-2017
Date [day=2, month=2, year=117]
它似乎有一个模式,但我似乎无法找到我在这里做错了什么!
您使用的 Date
方法根据计算机的时区设置给出日期,而 class 在内部存储 UTC 时区日期的午夜(0:00 小时)。如果您的时区在 UTC 以东(就像我的一样),那么您很幸运,日期是一致的;如果您 运行 在 UTC 以西的计算机上使用相同的代码,您将获得之前的日期。您绝对不希望您的代码如此脆弱。
除了:SimpleDateFormat
也使用了您计算机的时区设置,因此使用您发布的代码不会发现任何问题;但是你会从你的数据库中得到一个日期。
JB Nizet 在评论中提到这些方法已弃用。它们之所以被弃用,正是因为它们给了你如此脆弱的代码。
有两种解决方法:
- the
Date
documentation 提到你的可怜人,Calendar
class。 - 好的:
java.time.LocalDate
class 在 Java 8 中引入,也被移植回 Java 6 和 7。
让我们先拿好的:
LocalDate local = date.toInstant().atOffset(ZoneOffset.UTC).toLocalDate();
要对此进行测试,您可以使用这种方式生成与来自数据库的日期相等的日期:
date = Date.from(LocalDate.of(2017, 3, 19).atStartOfDay().atOffset(ZoneOffset.UTC).toInstant());
LocalDate
class 提供方法 getDayOfMonth()
、getMonth()
、getYear()
和许多其他方法,它们会给您预期的结果。我强烈希望您会发现这个 class 非常有吸引力,以至于您不需要自己的约会对象 class。如果要更改每个字段,可以使用 withDayOfMonth
、withMonth
和 withYear
方法。请注意,这些 return 新 LocalDate
对象具有新日期,而不是修改现有对象。 LocalDate
实例是不可变的。
如果您不能使用 Java 8 并且不想采用 Eugen Pechanec 在评论中提到的 ThreeTen Backport,您可以求助于 Calendar
class 中介绍的Java 1.1(那是很久以前的事了)。
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
cal.setTime(date);
DataBase.Date dateTemp = new DataBase.Date(cal.get(Calendar.DAY_OF_MONTH),
cal.get(Calendar.MONTH) + 1, cal.get(Calendar.YEAR));
要使用等于来自您数据库的日期进行测试:
DateFormat format = new SimpleDateFormat("dd-MM-yyyy");
format.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = format.parse(dateString);
我在 cal.get(Calendar.MONTH)
上加 1,因为 Calendar
的月份是从 0 开始的,而你想要一个从 1 开始的日期。
同样,您可以考虑使用 Calendar
而不是您自己的 class。它的 set
方法非常强大,以备不时之需。
为了完整起见,您得到的输出与 Date
class 的文档所说的完全一致。如果您想了解发生了什么(我希望如此),请参阅其 getDay, getMonth and getYear methods. And getDate().