将字符串日期转换为 yyyy-MM-dd'T'HH:mm:ss.SSSSSS 格式的字符串 java 7
Converting string date to string in yyyy-MM-dd'T'HH:mm:ss.SSSSSS format in java 7
我有以下日期
2017-08-23-11.19.02.234850
它具有以下日期格式
yyyy-MM-dd-HH.mm.ss.SSSSSS
我想做的是把日期转换成格式yyyy-MM-dd'T'HH:mm:ss.SSSSSS
我有以下代码
public static void main(String[] args) {
String strDate = "2017-08-23-11.19.02.234850";
String dateFmt = "yyyy-MM-dd-HH.mm.ss.SSSSSS";
System.out.println("converted Date: " + convertDate(strDate, dateFmt));
}
public static String convertDate(String strDate, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
sdf.setLenient(true);
try {
Date dateIn = sdf.parse(strDate);
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS").format(dateIn);
}catch(ParseException e) {
e.printStackTrace();
}
return "";
}
结果是
converted Date: 2017-08-23T11:22:56.000850
输入日期2017-08-23-11.19.02.234850
转换日期 2017-08-23T11:22:56.000850
看起来不一样,似乎 java 正在四舍五入毫秒,此外如果我关闭宽松的日期验证
sdf.setLenient(假);
我得到以下信息
java.text.ParseException: Unparseable date: "2017-08-23-11.19.02.234850"
at java.text.DateFormat.parse(Unknown Source)
at mx.santander.canonical.datamodel.enums.Main.convertDate(Main.java:74)
at mx.santander.canonical.datamodel.enums.Main.main(Main.java:66)
converted Date:
如何构建一个函数来以正确的方式验证和转换这样的日期字符串?
编辑:
我添加了一个获取结果的新函数
/**
* Gets the ISO 8601 date str from string.
*
* @param strDate the str date
* @return the ISO 8601 date str from string
*/
private String getISO8601DateStrFromString (String strDate) {
String responseISO8601Date = "";
if(strDate == null || "".equals(strDate.trim())) {
return responseISO8601Date;
}
try {
String strDtWithoutNanoSec = strDate.substring(0, strDate.lastIndexOf("."));
String strDtNanoSec = strDate.substring(strDate.lastIndexOf(".") + 1, strDate.length());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
formatter.setLenient(false);
Date date = formatter.parse(strDtWithoutNanoSec);
Timestamp t = new Timestamp(date.getTime());
t.setNanos(Integer.parseInt(strDtNanoSec));
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'");
NumberFormat nf = new DecimalFormat("000000");
responseISO8601Date = df.format(t.getTime()) + nf.format(t.getNanos());
} catch (ParseException | StringIndexOutOfBoundsException | NumberFormatException e) {
String errorMsg = String.format("The date provided for conversion to ISO 8601 format [%s] is not correct", strDate);
System.out.println(errorMsg);
}
return responseISO8601Date;
}
我得到的:
Uptadet date 2017-12-20T11:19:02.234850
日期只能精确到毫秒。请改用时间戳 - 它精确到纳秒,这在您的情况下是预期的。
请参考这个答案 - precision till nano seconds
A thin wrapper around java.util.Date that allows the JDBC API to
identify this as an SQL TIMESTAMP value. It adds the ability to hold
the SQL TIMESTAMP fractional seconds value, by allowing the
specification of fractional seconds to a precision of nanoseconds. A
Timestamp also provides formatting and parsing operations to support
the JDBC escape syntax for timestamp values.
SimpleDateFormat
of Java 不支持微秒模式。
java.util.Date format SSSSSS: if not microseconds what are the last 3 digits?
您有多种选择:
- 手动处理微秒的解析和格式化
- 切换为使用 Java 8 作为时间 API 支持模式中的小数秒 (https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)
- 如果您需要使用 Java 7,请考虑将 JODA Time 用于您的日期时间逻辑。 JODA 在其 DateTimeFormat (http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html)
中支持秒的小数部分
你得到的结果是意料之中的。在您的格式字符串中使用了 S
。 S
代表毫秒,hat 代表千分之一秒,在这种情况下,S
的数量对于解析无关紧要。
您输入的字符串以 11.19.02.234850
结尾,最后一部分被解释为整数值,并以毫秒的形式添加到日期和时间。即 234.850
秒。现在,如果您将 234
秒添加到 11:19:02
,它会变成 11:22:56
,就像您得到的结果一样...
您不能制作可以将微秒解析为 Date
的 SimpleDateFormat
掩码,并且 Date
也不能保存微秒值。
您必须选择,是要使用 Date
,还是真的需要比毫秒更精细的分辨率?
如果您坚持使用 Date
,您应该截断最后 3 个字符的字符串。
或者您可以使用 java.sql.Timestamp
,它有一个 valueOf()
method,帽子使用 SQL 时间戳格式。
不幸的是他和你的不完全一样(yyyy-[m]m-[d]d hh:mm:ss[.f...]
)...
另一种方法可能是通过分隔符(如 [-.]
)拆分字符串,将它们解析为整数,然后将这些整数与 Timestamp()
constructor...
一起使用
正如其他人已经提到的,您的要求不适合 Date
和 SimpleDateFormat
的使用,因为它们仅支持毫秒,即秒上的三位小数,而您有六位小数(微秒)。所以我们需要找到一些其他的方法。无论如何,这基本上是个好主意,因为 Date
和 SimpleDateFormat
早就过时了,今天我们有了更好的工具来完成这项工作。
我有两个建议给你。
java.time
即使在 Java 7 中,我认为使用 Java 8 中出现的现代 Java 日期和时间 API 是个好主意,又名 JSR -310。你能做到吗?当然;使用 Java 6 和 7,ThreeTen Backport 的反向端口。现代的 API 支持从 0 到 9 秒的任何小数位,当您知道如何操作时,代码很简单:
private static DateTimeFormatter inputParser
= DateTimeFormatter.ofPattern("yyyy-MM-dd-HH.mm.ss.SSSSSS");
private static DateTimeFormatter outputFormatter
= DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS");
public static String convertDate(String strDate) {
return LocalDateTime.parse(strDate, inputParser)
.format(outputFormatter);
}
我正在使用您自己的两种格式模式字符串。 convertDate("2017-08-23-11.19.02.234850")
returns 2017-08-23T11:19:02.234850
.
有一个可能的简化:由于您要获取的格式符合 ISO 8601,因此您不需要明确的格式化程序。现代 classes 理解并生成 ISO 8601 格式,所以你可以使用:
return LocalDateTime.parse(strDate, inputParser).toString();
但是,如果秒的小数点恰好以 000
结尾,则不会打印最后三个零。因此,即使在这种情况下也需要六位小数,请使用格式化程序。
正则表达式
如果你不想依赖外部库,即使是暂时的,直到你升级到 Java 8(或 9),你的工作可以用正则表达式来完成:
return strDate
.replaceFirst("^(\d{4}-\d{2}-\d{2})-(\d{2})\.(\d{2})\.(\d{2}\.\d{6})$",
"T::");
它不太优雅且难以阅读,并且它不提供您使用正确的日期和时间获得的输入验证级别 API。除此之外,这是一条路。
java.sql.Timestamp?
正如其他人所说,java.sql.Timestamp
提供纳秒精度,因此可以保存您的日期时间。不过,将您的字符串解析为 Timestamp
并不简单,所以我认为不值得这么麻烦。 正确地将 Timestamp.valueOf()
标识为要使用的方法,但在您这样做之前,您需要更改格式,因此您最终将更改格式两次而不是一次。或者可能是三次,因为 Timestamp
也不能轻松生成您想要的 ISO 8601 格式。此外,您还需要为时间戳决定一个时区,但我认为您可以毫无困难地做到这一点。
如果您需要保留日期时间,Timestamp
对象可能值得考虑,但同样,它已经过时 class。反正光是格式化,我是肯定不会用的。
您的代码中发生了什么?
SimpleDateFormat
将234850理解为毫秒,即234秒850毫秒。所以它为你的时间增加了 234 秒,11:19:02。然后按照您的要求在小数点后 6 位打印剩余的 850 毫秒。
我有以下日期
2017-08-23-11.19.02.234850
它具有以下日期格式
yyyy-MM-dd-HH.mm.ss.SSSSSS
我想做的是把日期转换成格式yyyy-MM-dd'T'HH:mm:ss.SSSSSS
我有以下代码
public static void main(String[] args) {
String strDate = "2017-08-23-11.19.02.234850";
String dateFmt = "yyyy-MM-dd-HH.mm.ss.SSSSSS";
System.out.println("converted Date: " + convertDate(strDate, dateFmt));
}
public static String convertDate(String strDate, String format) {
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.US);
sdf.setLenient(true);
try {
Date dateIn = sdf.parse(strDate);
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS").format(dateIn);
}catch(ParseException e) {
e.printStackTrace();
}
return "";
}
结果是
converted Date: 2017-08-23T11:22:56.000850
输入日期2017-08-23-11.19.02.234850 转换日期 2017-08-23T11:22:56.000850 看起来不一样,似乎 java 正在四舍五入毫秒,此外如果我关闭宽松的日期验证
sdf.setLenient(假);
我得到以下信息
java.text.ParseException: Unparseable date: "2017-08-23-11.19.02.234850"
at java.text.DateFormat.parse(Unknown Source)
at mx.santander.canonical.datamodel.enums.Main.convertDate(Main.java:74)
at mx.santander.canonical.datamodel.enums.Main.main(Main.java:66)
converted Date:
如何构建一个函数来以正确的方式验证和转换这样的日期字符串?
编辑:
我添加了一个获取结果的新函数
/**
* Gets the ISO 8601 date str from string.
*
* @param strDate the str date
* @return the ISO 8601 date str from string
*/
private String getISO8601DateStrFromString (String strDate) {
String responseISO8601Date = "";
if(strDate == null || "".equals(strDate.trim())) {
return responseISO8601Date;
}
try {
String strDtWithoutNanoSec = strDate.substring(0, strDate.lastIndexOf("."));
String strDtNanoSec = strDate.substring(strDate.lastIndexOf(".") + 1, strDate.length());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH.mm.ss");
formatter.setLenient(false);
Date date = formatter.parse(strDtWithoutNanoSec);
Timestamp t = new Timestamp(date.getTime());
t.setNanos(Integer.parseInt(strDtNanoSec));
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'");
NumberFormat nf = new DecimalFormat("000000");
responseISO8601Date = df.format(t.getTime()) + nf.format(t.getNanos());
} catch (ParseException | StringIndexOutOfBoundsException | NumberFormatException e) {
String errorMsg = String.format("The date provided for conversion to ISO 8601 format [%s] is not correct", strDate);
System.out.println(errorMsg);
}
return responseISO8601Date;
}
我得到的:
Uptadet date 2017-12-20T11:19:02.234850
日期只能精确到毫秒。请改用时间戳 - 它精确到纳秒,这在您的情况下是预期的。
请参考这个答案 - precision till nano seconds
A thin wrapper around java.util.Date that allows the JDBC API to identify this as an SQL TIMESTAMP value. It adds the ability to hold the SQL TIMESTAMP fractional seconds value, by allowing the specification of fractional seconds to a precision of nanoseconds. A Timestamp also provides formatting and parsing operations to support the JDBC escape syntax for timestamp values.
SimpleDateFormat
of Java 不支持微秒模式。
java.util.Date format SSSSSS: if not microseconds what are the last 3 digits?
您有多种选择:
- 手动处理微秒的解析和格式化
- 切换为使用 Java 8 作为时间 API 支持模式中的小数秒 (https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html)
- 如果您需要使用 Java 7,请考虑将 JODA Time 用于您的日期时间逻辑。 JODA 在其 DateTimeFormat (http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html) 中支持秒的小数部分
你得到的结果是意料之中的。在您的格式字符串中使用了 S
。 S
代表毫秒,hat 代表千分之一秒,在这种情况下,S
的数量对于解析无关紧要。
您输入的字符串以 11.19.02.234850
结尾,最后一部分被解释为整数值,并以毫秒的形式添加到日期和时间。即 234.850
秒。现在,如果您将 234
秒添加到 11:19:02
,它会变成 11:22:56
,就像您得到的结果一样...
您不能制作可以将微秒解析为 Date
的 SimpleDateFormat
掩码,并且 Date
也不能保存微秒值。
您必须选择,是要使用 Date
,还是真的需要比毫秒更精细的分辨率?
如果您坚持使用 Date
,您应该截断最后 3 个字符的字符串。
或者您可以使用 java.sql.Timestamp
,它有一个 valueOf()
method,帽子使用 SQL 时间戳格式。
不幸的是他和你的不完全一样(yyyy-[m]m-[d]d hh:mm:ss[.f...]
)...
另一种方法可能是通过分隔符(如 [-.]
)拆分字符串,将它们解析为整数,然后将这些整数与 Timestamp()
constructor...
正如其他人已经提到的,您的要求不适合 Date
和 SimpleDateFormat
的使用,因为它们仅支持毫秒,即秒上的三位小数,而您有六位小数(微秒)。所以我们需要找到一些其他的方法。无论如何,这基本上是个好主意,因为 Date
和 SimpleDateFormat
早就过时了,今天我们有了更好的工具来完成这项工作。
我有两个建议给你。
java.time
即使在 Java 7 中,我认为使用 Java 8 中出现的现代 Java 日期和时间 API 是个好主意,又名 JSR -310。你能做到吗?当然;使用 Java 6 和 7,ThreeTen Backport 的反向端口。现代的 API 支持从 0 到 9 秒的任何小数位,当您知道如何操作时,代码很简单:
private static DateTimeFormatter inputParser
= DateTimeFormatter.ofPattern("yyyy-MM-dd-HH.mm.ss.SSSSSS");
private static DateTimeFormatter outputFormatter
= DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS");
public static String convertDate(String strDate) {
return LocalDateTime.parse(strDate, inputParser)
.format(outputFormatter);
}
我正在使用您自己的两种格式模式字符串。 convertDate("2017-08-23-11.19.02.234850")
returns 2017-08-23T11:19:02.234850
.
有一个可能的简化:由于您要获取的格式符合 ISO 8601,因此您不需要明确的格式化程序。现代 classes 理解并生成 ISO 8601 格式,所以你可以使用:
return LocalDateTime.parse(strDate, inputParser).toString();
但是,如果秒的小数点恰好以 000
结尾,则不会打印最后三个零。因此,即使在这种情况下也需要六位小数,请使用格式化程序。
正则表达式
如果你不想依赖外部库,即使是暂时的,直到你升级到 Java 8(或 9),你的工作可以用正则表达式来完成:
return strDate
.replaceFirst("^(\d{4}-\d{2}-\d{2})-(\d{2})\.(\d{2})\.(\d{2}\.\d{6})$",
"T::");
它不太优雅且难以阅读,并且它不提供您使用正确的日期和时间获得的输入验证级别 API。除此之外,这是一条路。
java.sql.Timestamp?
正如其他人所说,java.sql.Timestamp
提供纳秒精度,因此可以保存您的日期时间。不过,将您的字符串解析为 Timestamp
并不简单,所以我认为不值得这么麻烦。 Timestamp.valueOf()
标识为要使用的方法,但在您这样做之前,您需要更改格式,因此您最终将更改格式两次而不是一次。或者可能是三次,因为 Timestamp
也不能轻松生成您想要的 ISO 8601 格式。此外,您还需要为时间戳决定一个时区,但我认为您可以毫无困难地做到这一点。
如果您需要保留日期时间,Timestamp
对象可能值得考虑,但同样,它已经过时 class。反正光是格式化,我是肯定不会用的。
您的代码中发生了什么?
SimpleDateFormat
将234850理解为毫秒,即234秒850毫秒。所以它为你的时间增加了 234 秒,11:19:02。然后按照您的要求在小数点后 6 位打印剩余的 850 毫秒。