现在是ISO 8601日期时间

时间:2016-03-10 07:30:05

标签: java c# date datetime

我需要在C#中使用的那种格式 DateTime.Now.ToString("o")DateTime.Now.ToString("o")的示例返回日期为

  

2016-03-10T11:24:59.7862749 + 04:00

然后在 sql中插入

  

2016-03-10 11:24:59.786

我试图从java插入相同的日期格式。我用的是:

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

并返回此

  

2016-03-10T07:29 + 0000

由于这种格式,它会出错。如何将格式更改为我想要的格式?

3 个答案:

答案 0 :(得分:6)

对于Java 7,您可以使用:

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
System.out.println(df.format(new Date()));

这使用了模式符号XXX,它也会在偏移内打印冒号。但是,对于Java-6,不提供此功能。并且精度始终限制在毫秒级。

对于Java-8,您还可以使用:

DateTimeFormatter dtf = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
System.out.println(OffsetDateTime.now().format(dtf)); // 2016-03-10T08:46:44.849+01:00

如果有这样的时钟(从Java-9开始),这将实现纳秒精度。

对于Java-6 ,要么应用基于SimpleDateFormat的hack,要么使用外部库:

// Java-6 (SimpleDateFormat)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String text = sdf.format(new Date());
text = text.substring(0, text.length() - 2) + ":" + text.substring(text.length() - 2);
System.out.println(text);

// Joda-Time
DateTime now = DateTime.now();
System.out.println(DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZ").print(now));

// Time4J
Moment now = SystemClock.currentMoment();
System.out.println(Iso8601Format.EXTENDED_DATE_TIME_OFFSET.withStdTimezone().format(now));

答案 1 :(得分:3)

Answer by Meno Hochschild是正确的。我只是添加一些注释和一些特定于SQL的代码。

避免旧的日期时间类

旧的日期时间类java.util.Date/.Calendar& java.text.SimpleDateFormat,设计糟糕,令人困惑,麻烦。避免它们。

旧的条款已经被Java 8及更高版本中内置的java.time框架所取代。

要在Java 8之前使用,请查看ThreeTen-Backport项目。

纳秒

java.time类具有纳秒分辨率。因此,由于旧类使用的毫秒级分辨率,2016-03-10T11:24:59.7862749+04:00被截断为2016-03-10 11:24:59.786,因此您不会遇到数据丢失问题。

由于遗留问题,获取Java 8中的当前时刻仅限于毫秒,小数点后三位数。 Java 9将以纳秒为单位获得当前时刻,最多可达十位小数九位数(假设您的计算机的硬件时钟可以提供如此精细的分辨率)。

ISO 8601

ISO 8601标准定义了日期时间值的合理文本格式。例如,2016-03-09T23:24:33Z2016-03-09T22:24:33-01:00。 java.time类默认使用这些,因此不需要定义解析模式。

即时

Instant是UTC时间轴上的一个时刻。

Instant instant = Instant.now();

调用Instant::toString以标准格式生成字符串。

String output = instant.toString();
  

2016-03-09T23:24:33.123Z

OffsetDateTime

应用ZoneOffset获取OffsetDateTime

ZoneOffset zoneOffset = ZoneOffset.ofHoursMinutes( -5 , 30 );
OffsetDateTime odt = OffsetDateTime.ofInstant( instant , zoneOffset );

ZonedDateTime

如果您知道完整时区而非offset-from-UTC,请应用ZoneId获取ZonedDateTime

使用proper time zone names

ZoneId zoneId = ZoneId.of( "Asia/Kolkata" ); // "Europe/Paris", "America/Montreal", etc.
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

java.sql.Timestamp

希望JDBC驱动程序将更新为直接使用java.time类型。在此之前,我们将转换为java.sql类型,以便在数据库中传输数据。

如上所述,java.time可以处理纳秒。 java.sql.Timestamp也是如此。但是您的数据库可能没有。某些数据库限制为整秒,毫秒或微秒。当数据通过JDBC传递到数据库时,数据库可能会被截断。

java.sql.Timestamp ts = java.sql.Timestamp.from( instant );

......走向另一个方向......

Instant instant = ts.toInstant();

请注意,根据定义,Instant始终为UTC。因此,无需在问题结束时执行尝试的那种代码。

工作流程

使用日期时,应尽可能减少字符串的使用。最大限度地使用有用的日期时间类/对象,即java.time类。不要将字符串视为日期时间值 - 它们是日期时间值的文本表示

不要将日期时间值作为字符串插入/从数据库中检索。使用java.sql.Timestampjava.sql.Date等java.sql对象。使用PreparedStatement和"设置/获取" setTimestamp / getTimestamp等方法。在数据库中虚拟always define your columnsTIMESTAMP WITH TIME ZONE而不是“没有时区”。

从数据库获取数据时,请使用java.sql类型。但是尽快转换为java.time类型。 java.sql类型是一个混乱,一个脏的黑客,应该只用于数据传输而不是业务逻辑。

通常最好在业务逻辑,数据存储,数据交换,API调用等中使用UTC。仅在用户需要或数据接收器要求时调整为时区。

答案 2 :(得分:2)

使用此格式" yyyy-MM-dd' H&H:mm:ss.SSSZ"

实施例

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");

System.out.println(df.format(new Date()));