获得ISO 8601格式的当前时刻UTC的最优雅的方式是什么?它看起来应该像:2010-10-12 t8: 50z。

例子:

String d = DateFormat.getDateTimeInstance(DateFormat.ISO_8601).format(date);

使用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());

使用SimpleDateFormat格式化任何日期对象:

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()将格式化当前时间。


Java 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”。


对于默认时区不是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时间,如果做许多不同的时间/日期操作… EDIT2:更正:setTimeZone不接受字符串(由Paul更正)


试试这个,

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

它的ISO 8601格式


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

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

返回一个字符串:

2012-07-10T16:02:48.440Z

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


这里优化了整个类,以便调用“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());
    }
}

Apache common -lang3中的DateFormatUtils有一些有用的常量,例如:ISO_DATETIME_FORMAT


ISO 8601可能包含秒 看到http://en.wikipedia.org/wiki/ISO_8601 *

所以代码应该是

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

适用于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);

乔达时间

更新:Joda-Time项目现在处于维护模式,团队建议迁移到java。时间类。对于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.time

对于Java 8和更高版本,Joda-Time继续工作。但是内置的java。时间框架取代了约达时间。因此,将代码从Joda-Time迁移到java。时间越方便越好。

查看我的另一个现代解决方案的答案。


关于java.time

java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。日期,日历和简单日期格式。

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

要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。

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

从哪里获取java。时间类?

Java SE 8、Java SE 9、Java SE 10以及更高版本 内置的。 带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小特性并进行了修复。 Java SE 6和Java SE 7 大部分的java。时间功能在ThreeTen-Backport中向后移植到Java 6和7。 安卓 后续版本的Android捆绑实现的java。时间类。 对于早期的Android (<26), ThreeTenABP项目适应ThreeTen-Backport(如上所述)。参见如何使用ThreeTenABP....

ThreeTen-Extra项目扩展了java。额外的课程时间。这个项目是未来可能添加到java.time的一个试验场。你可以在这里找到一些有用的类,比如Interval、YearWeek、YearQuarter等等。


Java 8原生

java。从Java 8开始,时间让它变得简单。线程安全。

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

结果:2015 - 04 - 14 - t11:07:36.639z

你可能会想使用更轻的时间,如即时或LocalDateTime, 但它们缺乏格式化程序支持或时区数据。 只有zone datetime可以开箱即用。

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

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

结果:2015 - 04 - 14 - t11:07:00 + 01:00(欧洲/巴黎)

细化的要求,如删除秒部分,仍然必须通过自定义格式或自定义post流程提供服务。

.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的后端端口。比如ThreeTen-Backport,它也有一个Android端口。 两者都比Joda轻,并从Joda的经验中学习-特别是考虑到java。时间是由Joda的作者设计的。


从Java 8开始,你可以简单地做:

Instant.now().toString();

来自java.time.Instant文档:

现在 公共静态即时现在() 从系统时钟中获取当前时刻。 这将查询系统UTC时钟以获得当前时刻。

 

toString toString() 使用ISO-8601表示法的该瞬间的字符串表示法。 使用的格式与DateTimeFormatter.ISO_INSTANT相同。


对于ISO 8601,您可以使用Java的SimpleDateFormat,格式如下:yyyy-MM-dd'T'HH:mm:ssXXX。

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

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()

虚拟机默认时区。更多的在这里

你可能会注意到,很少有时区的日期时间是以Z结尾的。这些时区与GMT的偏移量为“0”。

更多信息可以在这里找到。


不过,joda-time只支持扩展格式: “2015 - 12 - 09 - t00:22:42.930z” 不是最基本的: “20151209 t002242.930z” …我们最好使用java SimpleDateFormat测试一个格式列表。


我在Android中使用Calendar和SimpleDateFormat。下面的方法返回一个带有“GMT”时区的日历(这是通用时区)。然后,您可以使用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的存在。因此,如果调试一个日期,总是会看到当前时区的日期。


我相信最简单的方法是先去instant,然后去字符串,比如:

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

这将导致:

2017 - 09 - 08 - t12:56:45.331z


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());
}

他们应该添加一些简单的方法来从日期到即时,还有一个叫做toISO8601的方法,这是很多人都在寻找的。 作为对其他答案的补充,从java.util.Date到ISO 8601格式:

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

当使用自动补全时,它是不可见的,但是: java.time.Instant.toString ():

使用ISO-8601表示该时刻的字符串


DateTimeFormatter.ISO_DATE_TIME
        .withZone(ZoneOffset.UTC)
        .format(yourDateObject.toInstant())

博士tl;

其他一些答案在推荐java时是正确的。时间类,但会使用不必要的长度来满足您的特定需求。

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 - 23 t12:34z

即时:toString

instant类表示UTC时间,总是UTC时间。

Instant instant = Instant.now() ;

instant.toString (): 2018 - 01 - 23 t12:34:56.123456z

示例字符串2010-10-12T08:50Z的末尾的Z发音为“Zulu”,表示UTC。

您想要的格式恰好符合ISO 8601标准。java。时间类在解析/生成字符串时默认使用这些标准格式。因此不需要指定格式化模式。就像上面看到的那样调用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。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期-时间类,如java.util。日期,日历和简单日期格式。

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

要了解更多,请参阅Oracle教程。搜索Stack Overflow可以找到很多例子和解释。规范是JSR 310。

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

从哪里获取java。时间类?

Java SE 8、Java SE 9、Java SE 10以及更高版本 内置的。 带有捆绑实现的标准Java API的一部分。 Java 9增加了一些小特性并进行了修复。 Java SE 6和Java SE 7 大部分的java。时间功能在ThreeTen-Backport中向后移植到Java 6和7。 安卓 后续版本的Android捆绑实现的java。时间类。 对于早期的Android (<26), ThreeTenABP项目适应ThreeTen-Backport(如上所述)。参见如何使用ThreeTenABP....

ThreeTen-Extra项目扩展了java。额外的课程时间。这个项目是未来可能添加到java.time的一个试验场。你可以在这里找到一些有用的类,比如Interval、YearWeek、YearQuarter等等。


如果您关心性能,我创建了一个库,它在处理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"));
    }
}


对于那些使用Joda Time的人,这里有一个格式为yyyy-MM-dd' t ' hh:mm:ss' z '的一行代码

DateTime(timeInMillis, DateTimeZone.UTC).toString(ISODateTimeFormat.dateTimeNoMillis())