什么是最优雅的方式 UTC当前时刻的ISO 8601格式表示?它应该看起来像:2010-10-12T08:50Z
。
例:
String iso8601 = DateFormat.getDateTimeInstance(DateFormat.ISO_8601).format(date);
private static SimpleDateFormat
并不是线程安全的。
什么是最优雅的方式 UTC当前时刻的ISO 8601格式表示?它应该看起来像:2010-10-12T08:50Z
。
例:
String iso8601 = DateFormat.getDateTimeInstance(DateFormat.ISO_8601).format(date);
private static SimpleDateFormat
并不是线程安全的。
Answers:
使用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 将格式化当前时间。
"yyyy-MM-dd'T'HH:mmZ"
,每次我需要一个ISO-8601格式的日期时,我的应用程序中都必须有许多实例。随着JodaTime,因为我看到,我可以使用预先定义的格式ISODateTimeFormat
,它完成这个工作对我来说..
Z
是SimpleDateFormat中的有效模式,请执行以下操作:yyyy-MM-dd'T'HH:mm'Z'
。
对于默认时区不是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
如果经常需要,可以实例声明为全局常量,但是请注意,此类不是线程安全的。如果由多个线程同时访问,则必须同步。
编辑:如果进行许多不同的“时间/日期”操作,我希望使用乔达时间...编辑2
:纠正:setTimeZone
不接受字符串(由保罗纠正)
2016-06-14T13:56+0000
-问题是要求类似的东西2016-06-14T13:56Z
从Java 8开始,java.time使其变得简单,并且线程安全。
ZonedDateTime.now( ZoneOffset.UTC ).format( DateTimeFormatter.ISO_INSTANT )
结果: 2015-04-14T11:07:36.639Z
您可能会想使用打火机
Temporal
诸如Instant
或的LocalDateTime
,但它们缺少格式化程序支持或时区数据。只有ZonedDateTime
工作的开箱即用。
通过调整或链接ZonedDateTime和DateTimeFormatter的选项/操作,您可以轻松控制,可以在一定程度上时区和精度:
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的作者设计的。
return DateTimeFormatter.ISO_INSTANT.format(this);
DateTimeFormatter.ISO_INSTANT
并DateTimeFormatter.ISO_DATE_TIME
在秒后使用6位数字,而不是3位,而Spring不再使用3位数字@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
。
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”。
DateTime dt = new DateTime(); DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); String str = fmt.print(dt);
,或者您封装了return String.format("%tFT%<tRZ", new Date());
上一堂课,然后str = Iso8601Time.now()
在任何需要的地方做。(这并不是ISO格式会发生变化。)如果事实证明,您不仅需要ISO格式的当前日期,还可以使用lib。
%tFT%<tTZ
将包括秒;%tFT%<tTZ.%<tL
将包括毫秒。
从Java 8开始,您可以简单地执行以下操作:
Instant.now().toString();
现在
public static Instant now()
从系统时钟获取当前时刻。
这将查询系统UTC时钟以获得当前时刻。
public String toString()
使用ISO-8601表示形式的此瞬间的字符串表示形式。
使用的格式与相同
DateTimeFormatter.ISO_INSTANT
。
SimpleDateFormats
。
toString
,因此在许多情况下,您甚至不需要显式调用它。
使用JodaTime
ISO 8601日历系统是Joda-Time中的默认实现
这是JodaTime Formatter的文档
编辑:
如果您不想添加或看不到添加上述库的价值,则可以在内置SimpleDateFormat
类中使用,以将Date格式化为所需的ISO格式
如@Joachim Sauer所建议
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmZ");
String nowAsString = df.format(new Date());
ISODateTimeFormat
-ISO-8601的预定义格式化程序。
Apache的DateFormatUtilscommons-lang3
具有有用的常量,例如:DateFormatUtils.ISO_DATETIME_FORMAT
DateFormatUtils.format(new Date(), "yyyy-MM-dd'T'HH:mm'Z'", TimeZone.getTimeZone("UTC"));
在默认时区当前时刻:DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(new Date())
; @ yegor256感谢您的提及DateFormatUtils
,拥有apache commons-lang值得使用日期格式。
如果您不希望加入Jodatime(尽管如此)
javax.xml.bind.DatatypeConverter.printDateTime(
Calendar.getInstance(TimeZone.getTimeZone("UTC"))
);
返回一个字符串:
2012-07-10T16:02:48.440Z
与原始要求略有不同,但仍为ISO-8601。
ISO 8601可能包含秒数,请参见http://en.wikipedia.org/wiki/ISO_8601#Times
所以代码应该是
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
更新:该乔达时间的项目现在处于维护模式,与团队的建议迁移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 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添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
对于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);
您可以将Java的SimpleDateFormat与yyyy-MM-dd'T'HH:mm:ssXXX
ISO 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()
默认的虚拟机时区。这里更多
您可能会注意到几个以结尾的时区的日期时间'Z'
。这些时区'0'
与GMT的时间差为。
更多信息可以在这里找到。
我相信最简单的方法是先进入即时,然后像这样进行字符串化:
String d = new Date().toInstant().toString();
这将导致:
2017-09-08T12:56:45.331Z
Date
对象。做吧Instant.now().toString()
。如果您是Date
从旧版API获得的,则您的方法是最好的方法。
java.util.Date
,java.util.Calendar
和java.text.SimpleDateFormat
现在的遗产,由取代java.time内置到Java 8和更高等级。请参见Oracle 教程。
其他一些答案在推荐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 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添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
这是一个优化的整个类,因此,调用“ 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());
}
}
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());
}
不过,joda-time仅支持扩展格式:“ 2015-12-09T00:22:42.930Z”,不支持基本格式:“ 20151209T002242.930Z” ...我们最好使用Java SimpleDateFormat测试一系列格式。
我在Android中使用Calendar和SimpleDateFormat做到了。以下方法返回带有“ 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的存在。因此,如果调试一个日期,则始终会看到当前时区的日期。
如果您关心性能,则可以创建一个在处理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"));
}
}
他们应该添加一些简单的方法来从Date转换为Instant,并且还增加了一种称为的方法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())
尝试这个,
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSZ");
String date=sdf.format (new Date() );
对于ISO 8601格式