如何获取带有日期、小时和分钟的 ISO 8601 格式的当前时刻?

IT小君   2021-09-15T07:51:37

获取当前时刻 UTC 的ISO 8601格式表示的最优雅方式是什么它应该看起来像:2010-10-12T08:50Z

例子:

String iso8601 = DateFormat.getDateTimeInstance(DateFormat.ISO_8601).format(date);
点击广告,支持我们为你提供更好的服务
评论(22)
IT小君

使用SimpleDateFormat格式化任何Date你想要的对象:

TimeZone tz = TimeZone.getTimeZone("UTC");
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'"); // Quoted "Z" to indicate UTC, no timezone offset
df.setTimeZone(tz);
String nowAsISO = df.format(new Date());

使用new Date()如上所示的a将格式化当前时间。

2021-09-15T07:51:38   回复
IT小君

对于默认时区不是 UTC 的系统:

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

SimpleDateFormat,如果经常需要的情况下可以声明为一个全局常量,但要注意,这个类不是线程安全的。如果多个线程并发访问,则必须同步。

编辑:如果进行许多不同的时间/日期操作,我更喜欢 Joda Time...
EDIT2:更正:setTimeZone不接受字符串(由 Paul 更正)

2021-09-15T07:51:38   回复
IT小君

Java 8 原生

java.time从 Java 8开始就变得简单了。而且线程安全。

ZonedDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.ISO_INSTANT )

结果: 2015-04-14T11:07:36.639Z

您可能想使用Temporal诸如Instant或 之类的轻量级工具LocalDateTime,但它们缺乏格式化程序支持或时区数据。只能ZonedDateTime开箱即用。

通过调整或链接ZonedDateTimeDateTimeFormatter的选项/操作,您可以在一定程度上轻松控制时区精度

ZonedDateTime.now( ZoneId.of( "Europe/Paris" ) )
             .truncatedTo( ChronoUnit.MINUTES )
             .format( DateTimeFormatter.ISO_DATE_TIME )

结果: 2015-04-14T11:07:00+01:00[Europe/Paris]

细化的要求,例如删除秒部分,仍然必须由自定义格式或自定义后期处理提供服务。

.format( DateTimeFormatter.ISO_LOCAL_DATE_TIME ) // 2015-04-14T11:07:00
.format( DateTimeFormatter.ISO_LOCAL_DATE ) // 2015-04-14
.format( DateTimeFormatter.ISO_LOCAL_TIME ) // 11:07:00
.format( DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm" ) ) // 2015-04-14 11:07

对于 Java 6 和 7,您可以考虑 java.time 的后向端口,例如ThreeTen-Backport,它也有一个Android 端口两者都比 Joda 轻,并且从 Joda 的经验中吸取了教训——尤其是。考虑到 java.time 是由 Joda 的作者设计的。

2021-09-15T07:51:38   回复
IT小君

从 Java 8 开始,您可以简单地执行以下操作:

Instant.now().toString();

java.time.Instant文档:

现在

public static Instant now()

从系统时钟获取当前时刻。

这将查询系统 UTC 时钟以获取当前时刻。

 


public String toString()

使用 ISO-8601 表示的此瞬间的字符串表示。

使用的格式与DateTimeFormatter.ISO_INSTANT.

2021-09-15T07:51:38   回复
IT小君

爪哇 8:

thisMoment = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mmX")
                              .withZone(ZoneOffset.UTC)
                              .format(Instant.now());

Java 8 之前:

thisMoment = String.format("%tFT%<tRZ",
                           Calendar.getInstance(TimeZone.getTimeZone("Z")));

文档

'R'    24 小时制的时间格式为“%tH:%tM”
'F'    ISO 8601 完整日期格式为“%tY-%tm-%td”。

2021-09-15T07:51:39   回复
IT小君

使用JodaTime

ISO 8601 日历系统是 Joda-Time 中的默认实现

是 JodaTime Formatter 的文档

编辑:

如果您不想添加或看不到添加上述库的价值,您可以在内置SimpleDateFormat类中使用将日期格式化为所需的 ISO 格式

正如@Joachim Sauer 所建议的那样

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());
2021-09-15T07:51:39   回复
IT小君

来自 Apache 的DateFormatUtilscommons-lang3有一些有用的常量,例如:DateFormatUtils.ISO_DATETIME_FORMAT

2021-09-15T07:51:39   回复
IT小君

如果您不想包含 Jodatime(尽管它很好)

javax.xml.bind.DatatypeConverter.printDateTime(
    Calendar.getInstance(TimeZone.getTimeZone("UTC"))
);

它返回一个字符串:

2012-07-10T16:02:48.440Z

这与原始请求略有不同,但仍然是 ISO-8601。

2021-09-15T07:51:39   回复
IT小君

ISO 8601 可能包含秒见http://en.wikipedia.org/wiki/ISO_8601#Times

所以代码应该是

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
2021-09-15T07:51:40   回复
IT小君

tl;博士

其他一些答案在推荐java.time类方面是正确的,但会根据您的特定需求使用不必要的长度。

Instant.now()                               // Capture the current moment in UTC with a resolution as fines nanoseconds but usually in microseconds or milliseconds.
       .truncatedTo( ChronoUnit.MINUTES )   // Lop off any seconds or fractional second, to get a value in whole minutes.
       .toString()                          // Generate a String in standard ISO 8601 format where a `T` separates the year-month-day from the hour-minute-second, and the `Z` on the end for “Zulu” means UTC.

2018-01-23T12:34Z

Instant::toString

jav.time.Instant类表示UTC片刻,总是在UTC。

Instant instant = Instant.now() ;

Instant.toString(): 2018-01-23T12:34:56.123456Z

Z您的例子字符串的结尾2010-10-12T08:50Z的发音是“祖鲁”和指UTC

您想要的格式恰好符​​合ISO 8601标准。所述java.time类解析/生成字符串时默认使用这些标准格式。所以不需要指定格式模式。只需调用Instant::toString如上所示。

如果您特别想要没有秒或小数秒的整分钟,请截断。通过ChronoUnit指定时间单位

Instant instant = Instant.now().truncatedTo( ChronoUnit.MINUTES ) ;
String output = instant.toString();  // Generate a `String` object in standard ISO 8601 format.

关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle 教程并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本JDBC 驱动程序不需要字符串,不需要类。java.sql.*

从哪里获得 java.time 类?

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

2021-09-15T07:51:40   回复
IT小君

乔达时间

更新:乔达时间的项目现在处于维护模式,与团队的建议迁移java.time类。对于 Java 6 和 7,请参阅ThreeTen-Backport项目,在ThreeTenABP项目中进一步适用于 Android

使用Joda-Time库…

String output = new DateTime( DateTimeZone.UTC ).toString() ;

这是线程安全的。Joda-Time 创建新的不可变对象而不是更改现有对象。

如果你真的想要一个没有秒的格式,解析为分钟,那么使用 Joda-Time 中的许多其他内置格式器之一。

DateTime now = new DateTime( DateTimeZone.UTC ) ;
String output = ISODateTimeFormat.dateHourMinute.print( now ) ;

时间

对于 Java 8 及更高版本,Joda-Time 继续工作。但是内置的java.time框架取代了 Joda-Time。因此,请尽快将您的代码从 Joda-Time 迁移到 java.time。

有关现代解决方案,请参阅我的其他答案


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle 教程并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本JDBC 驱动程序不需要字符串,不需要类。java.sql.*

从哪里获得 java.time 类?

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多

2021-09-15T07:51:40   回复
IT小君

对于 Java 版本 7

您可以遵循 Oracle 文档:http : //docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

X - 用于 ISO 8601 时区

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

System.out.println(nowAsISO);

DateFormat df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
//nowAsISO = "2013-05-31T00:00:00Z";
Date finalResult = df1.parse(nowAsISO);

System.out.println(finalResult);
2021-09-15T07:51:41   回复
IT小君

我确实相信最简单的方法是首先进入 Instant 然后像这样的字符串:

String d = new Date().toInstant().toString();

这将导致:

2017-09-08T12:56:45.331Z

2021-09-15T07:51:41   回复
IT小君

您可以将 Java 的SimpleDateFormatyyyy-MM-dd'T'HH:mm:ssXXXISO 8601的以下模式一起使用

示例代码:(列出所有可用时区)

for (String timeZone : TimeZone.getAvailableIDs())
{
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    dateFormat.setTimeZone(TimeZone.getTimeZone(timeZone));
    String formatted = dateFormat.format(new Date());
    System.out.print(formatted);

    if (formatted.endsWith("Z"))
    {
        // These time zone's have offset of '0' from GMT.
        System.out.print("\t(" + timeZone + ")");
    }

    System.out.println();
}

你可以使用:

TimeZone.getDefault()

对于默认的 vm 时区。更多在这里

您可能会注意到几个以 结尾的时区的日期时间'Z'这些时区'0'与 GMT有偏差

更多信息可以在这里找到

2021-09-15T07:51:42   回复
IT小君
private static String getCurrentDateIso()
{
    // Returns the current date with the same format as Javascript's new Date().toJSON(), ISO 8601
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    return dateFormat.format(new Date());
}
2021-09-15T07:51:42   回复
IT小君

这是一个优化的整个类,因此调用“now()”不会做任何它必须做的事情。

public class Iso8601Util
{
    private static TimeZone tz = TimeZone.getTimeZone("UTC");
    private static DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm'Z'");

    static
    {
        df.setTimeZone(tz);
    }

    public static String now()
    {
        return df.format(new Date());
    }
}
2021-09-15T07:51:42   回复
IT小君

尽管如此,joda-time 只支持扩展格式:“2015-12-09T00:22:42.930Z”而不是基本格式:“20151209T002242.930Z”……我们最好用 java SimpleDateFormat 测试格式列表。

2021-09-15T07:51:42   回复
IT小君

我使用 Calendar 和 SimpleDateFormat 在 Android 中做到了。以下方法返回带有“GMT”时区(这是通用时区)的日历。然后,您可以使用 Calendar 类设置不同时区之间的小时,使用 Calendar 类的 setTimeZone() 方法。

private static final String GMT = "GMT";
private static final String DATE_FORMAT_ISO = "yyyyMMdd'T'HHmmss";

public static Calendar isoToCalendar(final String inputDate) {
    Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(GMT));
    try {
        SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_ISO, Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone(GMT));
        Date date = dateFormat.parse(inputDate);
        calendar.setTime(date);
    } catch (ParseException e) {
        Log.e("TAG",e.getMessage());
    }
    return calendar;
}

记住: Date 类不知道 TimeZone 的存在。因此,如果您调试一个日期,您总是会看到当前时区的日期。

2021-09-15T07:51:42   回复
IT小君
DateTimeFormatter.ISO_DATE_TIME
        .withZone(ZoneOffset.UTC)
        .format(yourDateObject.toInstant())
2021-09-15T07:51:43   回复
IT小君

如果您关心性能,我创建了一个,它在处理 ISO8601 格式的日期方面优于标准 Java 解析器和格式化程序。DatetimeProcessor 实现是线程安全的,可以缓存在并发映射或静态字段中。

<dependency>
  <groupId>com.axibase</groupId>
  <artifactId>date-processor</artifactId>
  <version>1.0.3</version>
</dependency>
import com.axibase.date.DatetimeProcessor;
import com.axibase.date.PatternResolver;
import org.junit.Before;
import org.junit.Test;

import java.time.Clock;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;

public class DateFormatTest {
    private Clock clock;

    @Before
    public void prepare() {
        clock = Clock.fixed(Instant.ofEpochMilli(1571285405300L), ZoneId.of("Europe/Berlin"));
    }

    @Test
    public void testIsoMillis(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("iso");
        assertThat(formatter.print(clock.millis(), ZoneOffset.UTC), is("2019-10-17T04:10:05.300Z"));
    }

    @Test
    public void testIsoMillisLocalZone(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("iso");
        assertThat(formatter.print(clock.millis(), clock.getZone()), is("2019-10-17T06:10:05.300+02:00"));
    }

    @Test
    public void testIsoMinutes(){
        final DatetimeProcessor formatter = PatternResolver.createNewFormatter("yyyy-MM-ddTHH:mmXXX");
        assertThat(formatter.print(clock.millis(), ZoneOffset.UTC), is("2019-10-17T04:10Z"));
    }
}

2021-09-15T07:51:43   回复
IT小君

他们应该添加某种从 Date 到 Instant 的简单方法,以及一种称为 的方法toISO8601,这是很多人正在寻找的。作为对其他答案的补充,从 java.util.Date 到 ISO 8601 格式:

Instant.ofEpochMilli(date.getTime()).toString();

使用自动完成功能时它并不真正可见,但是 java.time.Instant.toString()::

使用 ISO-8601 的这一瞬间的字符串表示

2021-09-15T07:51:43   回复
IT小君

尝试这个,

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZ");
        String date=sdf.format (new Date() );

其为 ISO 8601 格式

2021-09-15T07:51:43   回复