使用java 1.7从postgres检索时日期格式不一致

使用java 1.7从postgres检索时日期格式不一致,java,postgresql,date,Java,Postgresql,Date,在从postgres检索日期列值并使用JDK1.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/

在从postgres检索日期列值并使用JDK1.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被附加在那些日期部分大于12的日期值上。当我查看数据库时,我没有看到任何AM/PM。在我的DO中,我刚刚将变量声明为Date

请让我知道为什么会出现这种格式不一致的情况

谢谢

以下是我如何将日期设置为我的DO

public void setCreatedDate(Date createdDate) { 
  if (createdDate == null) { 
    this.mCreatedDate = createdDate; return; 
  }
  this.mCreatedDate = new Date(createdDate.getTime());
} 

我根本没有使用任何格式代码。即使有一个,我也不确定为什么它不应用于所有记录

您需要了解,使用日期时间数据类型存储在数据库中的日期时间值没有格式。您看到的是为方便人类查看而生成的日期时间值的字符串表示形式。字符串不是日期时间

因此,“AM/PM”的格式问题与在Postgres之外生成该字符串的某些代码有关。您没有向我们显示该代码,因此我们无法直接解决该问题。但是,如果您有意识地使用日期时间值/对象而不是字符串,那么首先可以避免这个问题

在Postgres中存储日期和时间 在Postgres中,您通常应该使用带有时区的
时间戳
数据类型。这种类型实际上并不保留时区。相反,它尊重时区,使用随数据输入一起传递的任何偏移量或时区信息进行调整。然后将结果存储在数据库中。调整后,Postgres丢弃原始偏移量或时区信息

从Postgres检索日期时间 检索数据时(a
SELECT
),您可能会获得日期时间值或字符串,具体取决于客户端应用程序(pgAdmin、psql等)或数据库驱动程序(等)。如果获得一个字符串,可能会代表您对某个时区进行调整,但该字符串不是日期时间值。如果要获取日期时间值,请在工作中使用该值,而不是转换为字符串。例如,在JDBC中,这意味着使用对象

Java日期时间框架 如果使用Java8或更高版本的技术,您应该使用新的。如果不可能,请使用库。尽量避免使用java.util.Date/.Calendar&java.text.simpleDataFormat,因为它们既麻烦又容易混淆

例子 下面是从Postgres 9.4中提取
java.sql.Timestamp
的完整示例,然后使用java.time或Joda-time处理该值

Joda Time和java.util.Date的数据丢失 请注意,Joda时间(如java.util.Date)被限制为小数秒的精度。博士后决心学习英语。因此,将Postgres转换为Joda Time/java.util.Date意味着可能会丢失数据。有了java.time,它解决的问题就没有了

代码 用Java8Update51编写,使用MacOSX MountainLion上9.4.x的驱动程序

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.sql.Timestamp 小心旧的Java日期时间类如何隐式应用JVM的当前默认时区。虽然本打算有所帮助,但却造成了无尽的困惑。运行此代码时看到的时区是偏移量为
−07:00

String output_SqlTimestamp = ts.toString();  // Confusingly applies your JVM’s current default time zone.
java.time 在Java8及更高版本中使用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 );
乔达时间 在Java8之前,使用Joda时间

// 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 );
跑步的时候

输出时间戳:2015-08-24 12:46:06.979144 输出UTC:2015-08-24T18:46:06.979144Z 输出:2015-08-24T14:46:06.979144-04:00[美国/蒙特利尔] 输出日期:2015-08-24T14:46:06.979-04:00 输出时间UTC:2015-08-24T18:46:06.979Z
日期(或时间戳)在数据库中没有任何格式。无论您看到的是什么格式,都由您的代码应用。您检索的数据不正确或格式不正确。您使用什么代码导出CSV?(如果您将任何代码粘贴到问题中,而不是在注释中,这可能是最好的)如何从数据库检索数据?(向我们展示SQL查询和处理
ResultSet
的代码)如何将值输出到CSV文件?(显示写入输出文件的代码)。如果您的列确实是
日期
,则这些值不应包含时间部分。如果使用您最喜欢的SQL客户机查看数据,您会看到什么?如果使用SQL客户机使用
to_char()
格式化日期,您会得到什么?