我在从postgres检索日期列值并使用JDK 1.7导出为CSV时遇到此独特问题以下是示例输出
ID, Date Created, Date Modified
816271, 8/8/2013 14:35 2/2/2015 16:47
830322 13/08/2013 11:48 AM 2/2/2015 16:48
1128312 10/2/2015 16:53 10/2/2015 16:53
1129465 12/2/2015 16:23 12/2/2015 16:23
1130482 16/02/2015 4:28 PM 15/06/2015 7:01 AM
1019527 19/08/2014 4:40 AM 23/02/2015 12:14 PM
1134334 23/02/2015 8:38 AM 4/6/2015 5:16
问题是,我看到AM / PM附加了DAY部分大于12的日期值。当我查看数据库时,我看不到任何AM / PM。在我的DO中,我刚刚将变量声明为Date。
请让我知道为什么会出现这种不一致的格式化。
感谢
以下是我如何将日期设置到DO中。
public void setCreatedDate(Date createdDate) {
if (createdDate == null) {
this.mCreatedDate = createdDate; return;
}
this.mCreatedDate = new Date(createdDate.getTime());
}
我根本没有使用任何格式化代码。即使有一个,我也不确定为什么它不适用于所有记录
答案 0 :(得分:1)
您需要了解使用日期时间数据类型存储在数据库中的日期时间值没有格式。您所看到的是为方便人类查看而生成的日期时间值的字符串表示。字符串不日期时间。
因此,“AM / PM”的格式问题与Postgres之外生成该字符串的一些代码有关。您没有向我们展示该代码,因此我们无法直接解决该问题。但是如果你有意识地使用日期时间值/对象而不是字符串,你可以首先避免这个问题。
在Postgres中,您通常应该使用TIMESTAMP WITH TIME ZONE
数据类型。此类型实际上不保留时区。而是它尊重时区,使用伴随数据输入的任何传递的偏移或时区信息来调整到UTC。然后将结果存储在数据库中。调整后,Postgres会丢弃原始偏移或时区信息。
检索数据(SELECT
)时,您可能会得到一个日期时间值,或者您可能会获得一个字符串,具体取决于客户端应用程序(pgAdmin,psql,SQuirreL SQL Client等)或者您的数据库驱动程序(JDBC等)。如果获取字符串,则可能代表您对某个时区进行了调整,但该字符串不日期时间值。如果获取日期时间值,请坚持使用该值进行工作,而不是转换为字符串。在JDBC中,这意味着使用java.sql.Timestamp
个对象,例如。
如果使用Java 8或更高版本的技术,则应使用新的java.time package。如果不可能,请使用Joda-Time库。尽量避免使用java.util.Date/.Calendar& java.text.SimpleDateFormat因为它们很麻烦而且令人困惑。
下面是从Postgres 9.4中提取java.sql.Timestamp
,然后使用java.time或Joda-Time处理值的完整示例。
请注意,Joda-Time(如java.util.Date)仅限于小数秒的millisecond精度。 Postgres解析为microseconds。因此,从Postgres转换为Joda-Time / java.util.Date意味着可能会丢失数据。使用java.time,没有问题,因为它解析为nanoseconds。
使用postgresql-9.4-1201.jdbc41.jar
驱动程序和Mac OS X Mountain Lion上的Postgres 9.4.x编写的Java 8 Update 51。
String message = "Example of fetching Timestamp from Postgres.";
StringBuilder sql = new StringBuilder();
sql.append( "SELECT now() " + "\n" );
sql.append( ";" );
java.sql.Timestamp ts = null;
try ( Connection conn = DatabaseHelper.instance().connectionInAutoCommitMode() ;
PreparedStatement pstmt = conn.prepareStatement( sql.toString() ); ) {
try ( ResultSet rs = pstmt.executeQuery(); ) {
// Extract data from result set
int count = 0;
while ( rs.next() ) {
count ++;
ts = rs.getTimestamp( 1 );
}
}
} catch ( SQLException ex ) {
logger.error( "SQLException during: " + message + "\n" + ex );
} catch ( Exception ex ) {
logger.error( "Exception during: " + message + "\n" + ex );
}
请注意旧的Java日期时间类如何隐式应用JVM的当前默认时区。虽然旨在提供帮助,但它不会造成混乱。运行此代码时看到的时区为America/Los_Angeles
,其偏移量为−07:00
。
String output_SqlTimestamp = ts.toString(); // Confusingly applies your JVM’s current default time zone.
在Java 8及更高版本中使用java.time。
// If you have Java 8 or later, use the built-in java.time package.
java.time.Instant instant = ts.toInstant();
java.time.ZoneId zoneId = ZoneId.of( "America/Montreal" );
java.time.ZonedDateTime zdt = java.time.ZonedDateTime.ofInstant( instant , zoneId );
String output_UTC = instant.toString();
String output_Montréal = zdt.toString();
System.out.println( "output_SqlTimestamp: " + output_SqlTimestamp );
System.out.println( "output_UTC: " + output_UTC );
System.out.println( "output_Montréal: " + output_Montréal );
在Java 8之前,使用Joda-Time。
// Before Java 8, use Joda-Time. (Joda-Time was the inspiration for java.time.)
// IMPORTANT: Joda-Time, like java.util.Date, is limited to milliseconds for fraction of a second. So you may experience data loss from a Postgres date-time value with microseconds.
org.joda.time.DateTime dateTimeMontréal = new org.joda.time.DateTime( ts.getTime() , DateTimeZone.forID( "America/Montreal" ) ); // WARNING: Data lost with microseconds truncated to milliseconds.
org.joda.time.DateTime dateTimeUtc = dateTimeMontréal.withZone( DateTimeZone.UTC );
String output_Joda_dateTimeMontréal = dateTimeMontréal.toString();
String output_Joda_dateTimeUtc = dateTimeUtc.toString();
System.out.println( "output_Joda_dateTimeMontréal: " + output_Joda_dateTimeMontréal );
System.out.println( "output_Joda_dateTimeUtc: " + output_Joda_dateTimeUtc );
跑步时。
output_SqlTimestamp: 2015-08-24 12:46:06.979144
output_UTC: 2015-08-24T18:46:06.979144Z
output_Montréal: 2015-08-24T14:46:06.979144-04:00[America/Montreal]
output_Joda_dateTimeMontréal: 2015-08-24T14:46:06.979-04:00
output_Joda_dateTimeUtc: 2015-08-24T18:46:06.979Z