简体   繁体   English

在Java 7中将字符串日期转换为yyyy-MM-dd'T'HH:mm:ss.SSSSSS格式的字符串

[英]Converting string date to string in yyyy-MM-dd'T'HH:mm:ss.SSSSSS format in java 7

I have the following date 我有以下日期

2017-08-23-11.19.02.234850 2017-08-23-11.19.02.234850

it has the following date format 它具有以下日期格式

yyyy-MM-dd-HH.mm.ss.SSSSSS yyyy-MM-dd-HH.mm.ss.SSSSSS

What I want to do is to convert the date to format yyyy-MM-dd'T'HH:mm:ss.SSSSSS 我要做的是将日期转换为yyyy-MM-dd'T'HH:mm:ss.SSSSSS

I have the following code 我有以下代码

    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 "";
    }

the result is 结果是

converted Date: 2017-08-23T11:22:56.000850

input date 2017-08-23-11.19.02.234850 converted date 2017-08-23T11:22:56.000850 doesn't look the same, it seems java is rounding the milliseconds besides if I turn lenient off for date validation 输入日期2017-08-23-11.19.02.234850转换日期2017-08-23T11:22:56.000850看起来不一样,似乎Java舍入了毫秒数,如果我关闭宽大日期验证

sdf.setLenient(false); sdf.setLenient(false);

I get the following 我得到以下

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:

How to build a function which validates and converts date strings like this in a proper way? 如何建立一个以正确的方式验证和转换日期字符串的函数?


EDIT: 编辑:

I added a new function to obtain results 我添加了一个新功能以获得结果

/**
      * 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;
     }

What I get: 我得到的是:

Uptadet date 2017-12-20T11:19:02.234850 更新日期2017-12-20T11:19:02.234850

As others have already mentioned, your requirement does not fit the use of Date and SimpleDateFormat since these only support milliseconds, that is, three decimals on the seconds, where you have six decimals (microseconds). 正如其他人已经提到的那样,您的要求不适合使用DateSimpleDateFormat因为它们仅支持毫秒,即秒数为三位小数,其中您有六位小数(微秒)。 So we need to find some other way. 因此,我们需要找到其他方法。 This is basically a good idea anyway, since Date and SimpleDateFormat are long outdated, and today we have better tools for the job. 无论如何,这基本上是一个好主意,因为DateSimpleDateFormat早已过时,并且今天我们有更好的工具来完成这项工作。

I have got two suggestions for you. 我有两个建议给你。

java.time java.time

Even in Java 7 I think that it's a good idea to use the modern Java date and time API that came out with Java 8, AKA JSR-310. 即使在Java 7中,我也认为使用Java 8(即AKA JSR-310)附带的现代Java日期和时间API是一个好主意。 Can you do that? 你能做到吗? Certainly; 当然; use the backport for Java 6 and 7, ThreeTen Backport . 将backport用于Java 6和7, ThreeTen Backport The modern API supports anything from 0 through 9 decimals on the seconds, and the code is straightforward when you know how: 现代的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);
}

I am using your own two format pattern strings. 我正在使用自己的两种格式模式字符串。 convertDate("2017-08-23-11.19.02.234850") returns 2017-08-23T11:19:02.234850 . convertDate("2017-08-23-11.19.02.234850")返回2017-08-23T11:19:02.234850

There is a simplification possible: Since the format you want to obtain, conforms with ISO 8601, you don't need an explicit formatter for it. 有一个可能的简化:由于您要获取的格式符合ISO 8601,因此不需要显式格式化程序。 The modern classes understand and produce ISO 8601 formats natively, so you may use: 现代类可以本地理解和生成ISO 8601格式,因此您可以使用:

    return LocalDateTime.parse(strDate, inputParser).toString();

However, if the decimals on the seconds happened to end in 000 , this will not print the last three zeroes. 但是,如果秒的小数点恰好以000结尾,则不会输出最后三个零。 So if six decimals are required even in this case, use the formatter. 因此,即使在这种情况下也需要六位小数,请使用格式化程序。

Regular expression 正则表达式

If you don't want to rely on an external library, even temporarily until once you upgrade to Java 8 (or 9), your job can be done with a regular expression: 如果您不想依赖外部库,即使只是暂时不依赖于外部库,直到升级到Java 8(或9)后,都可以使用正则表达式来完成工作:

    return strDate
            .replaceFirst("^(\\d{4}-\\d{2}-\\d{2})-(\\d{2})\\.(\\d{2})\\.(\\d{2}\\.\\d{6})$",
                    "$1T$2:$3:$4");

It's less elegant and harder to read, and it doesn't offer the level of input validation you get from using a proper date and time API. 它不那么优雅,更难阅读,并且不提供使用正确的日期和时间API所获得的输入验证级别。 Other than that, it's a way through. 除此之外,这是一条路。

java.sql.Timestamp? java.sql.Timestamp?

As others have said, java.sql.Timestamp offers nanosecond precision and thus will hold your date-time. 就像其他人所说的那样, java.sql.Timestamp提供了纳秒级的精度,因此将保留您的日期时间。 Parsing your string into a Timestamp isn't straightforward, though, so I don't think it's worth the trouble. 但是,将字符串解析为Timestamp并不是一件容易的事,因此我认为这样做不值得。 Usagi Miyanmoto correctly identifies Timestamp.valueOf() as the method to use, but before you could do that, you would have change the format, so you would end up changing the format twice instead of just once. Usagi Miyanmoto正确地将Timestamp.valueOf()标识为要使用的方法,但是在您可以执行此操作之前,您已经更改了格式,因此最终将更改格式两次,而不是一次。 Or maybe three times since Timestamp also doesn't produce your desired ISO 8601 format readily. 也许是三遍,因为Timestamp也无法轻松生成所需的ISO 8601格式。 Additionally you would need to decide a time zone for the timestamp, but I assume you could do that without any trouble. 另外,您需要确定时间戳的时区,但是我认为您可以做到这一点而没有任何麻烦。

If you needed to keep the the date-time around, a Timestamp object might be worth considering, but again, it's a long outdated class. 如果您需要保持日期时间不变,则可能值得考虑使用Timestamp对象,但这又是一个过时的类。 In any case, for reformatting alone, I certainly would not use it. 无论如何,仅凭格式重新格式化,我当然不会使用它。

What happened in your code? 您的代码中发生了什么?

SimpleDateFormat understood 234850 as milliseconds, that is, 234 seconds 850 milliseconds. SimpleDateFormat将234850理解为​​毫秒,即234秒为850毫秒。 So it added 234 seconds to your time, 11:19:02. 因此,它为您的时间增加了234秒11:19:02。 And then printed the remaining 850 milliseconds in 6 decimal places as you had requested. 然后按要求将剩余的850毫秒打印在小数点后6位。

Date has precision only till milli seconds. 日期只能精确到毫秒。 Please use timestamp instead - it has precision till nano seconds, which is expected in your case. 请改用timestamp-它的精度可以达到纳秒,这在您的情况下是可以预期的。

Please refer this answer - precision till nano seconds 请参考此答案- 精确到纳秒

TimeStamp API 时间戳API

A thin wrapper around java.util.Date that allows the JDBC API to identify this as an SQL TIMESTAMP value. 围绕java.util.Date的瘦包装器,该包装器允许JDBC API将其标识为SQL TIMESTAMP值。 It adds the ability to hold the SQL TIMESTAMP fractional seconds value, by allowing the specification of fractional seconds to a precision of nanoseconds . 通过允许小数秒的精度达到纳秒精度,它增加了保存SQL TIMESTAMP小数秒值的能力。 A Timestamp also provides formatting and parsing operations to support the JDBC escape syntax for timestamp values. 时间戳还提供格式化和解析操作,以支持时间戳值的JDBC转义语法。

SimpleDateFormat of Java does not support microsecond in pattern. Java的SimpleDateFormat不支持微秒模式。

java.util.Date format SSSSSS: if not microseconds what are the last 3 digits? java.util.Date格式SSSSSS:如果不是毫秒,则最后3位数字是多少?

You have several choices: 您有几种选择:

  1. Manually handle the parsing and formatting of the microseconds 手动处理微秒的解析和格式化
  2. Switch to use Java 8 as Time API supports fraction of second in pattern ( https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html ) 切换为使用Java 8,因为Time API支持秒级模式( https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
  3. If you need to use Java 7, consider using JODA Time for your date-time logics. 如果需要使用Java 7,请考虑将JODA Time用于日期时间逻辑。 JODA support fraction of second in its DateTimeFormat ( http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html ) JODA在其DateTimeFormat中支持秒级( http://joda-time.sourceforge.net/apidocs/org/joda/time/format/DateTimeFormat.html

That result you got is expected. 您得到的结果是预期的。 In your format string S were used. 在您的格式字符串S被使用。 S is for milliseconds, hat is thousandths of seconds, and in this case the number of S 's does not matter for parsing. S为毫秒,hat为千分之一秒,在这种情况下, S的数目对于解析而言无关紧要。
Your input string ends with 11.19.02.234850 , the last part is interpreted as an integer value, and added to the date and time as milliseconds. 您输入的字符串以11.19.02.234850 ,最后一部分被解释为整数值,并以毫秒为单位添加到日期和时间。 That is as 234.850 seconds. 那就是234.850秒。 Now, if you add 234 secs to 11:19:02 , it becomes 11:22:56 , just as you got in the result... 现在,如果您将234秒添加到11:19:02 ,则它变为11:22:56 ,就像您得到的结果一样...

You cannot make a SimpleDateFormat mask that can parse microseconds into a Date , and Date cannot hold microseconds value either. 您不能创建可以将微秒解析为DateSimpleDateFormat掩码,并且Date也不可以包含微秒的值。

You have to choose, whether you want to use Date , or really need the finer then milliseconds resolution? 您必须选择是否要使用Date ,还是真的需要更好的毫秒级分辨率?

If you stick with Date , you should truncate the string of the last 3 characters. 如果坚持使用Date ,则应截断最后3个字符的字符串。

Or you could use java.sql.Timestamp , which has a valueOf() method , hat uses SQL timestamp format. 或者,您可以使用具有valueOf()方法的 java.sql.Timestamp ,并使用SQL时间戳格式。
Unfortunately it is not exactly he same as yours (being yyyy-[m]m-[d]d hh:mm:ss[.f...] )... 不幸的是,他与您的并不完全相同(是yyyy-[m]m-[d]d hh:mm:ss[.f...] )...
Another way could be to split the string by separators (like [-.] ), parse them to integers, and use hese integers with the Timestamp() constructor ... 另一种方法是用分隔符(如[-.] )分割字符串,将其解析为整数,然后将这些整数与Timestamp()构造函数一起使用 ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 java.text.ParseException:Unparseable date:yyyy-MM-dd HH:mm:ss.SSSSSS - java.text.ParseException: Unparseable date: yyyy-MM-dd HH:mm:ss.SSSSSS 将日历对象转换为java格式的字符串,格式为“yyyy-mm-dd hh:mm:ss” - converting a calendar object into a string in java with format “yyyy-mm-dd hh:mm:ss” 格式为“ yyyy-mm-dd HH:mm:ss.SSSS”的Java String to Date对象 - Java String to Date object of the format “yyyy-mm-dd HH:mm:ss.SSSS” 格式为“yyyy-mm-dd HH:mm:ss”的 Java String to Date 对象 - Java String to Date object of the format “yyyy-mm-dd HH:mm:ss” Java 字符串日期到 XMLGregorianCalendar whit 格式 yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z' - Java String date to XMLGregorianCalendar whit format yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z' Java 格式 yyyy-MM-dd'T'HH:mm:ss.SSSz 到 yyyy-mm-dd HH:mm:ss - Java format yyyy-MM-dd'T'HH:mm:ss.SSSz to yyyy-mm-dd HH:mm:ss 将字符串转换为“yyyy-MM-dd HH:mm:ss”时无法解析的日期异常 - Unparseable date exception when converting a string to “yyyy-MM-dd HH:mm:ss” 字符串(dd-MM-yyyy HH:mm)到日期(yyyy-MM-dd HH:mm)| Java的 - String (dd-MM-yyyy HH:mm) to Date (yyyy-MM-dd HH:mm) | Java 我们如何在 Java 中将 yyyy-MM-dd-HH.mm.ss.SSSSSS 转换为 yyyy-MM-dd'T'HH:mm:ss.SSSz? - How we can convert yyyy-MM-dd-HH.mm.ss.SSSSSS to yyyy-MM-dd'T'HH:mm:ss.SSSz in Java? 将此“yyyy-MM-dd'T'HH:mm:ss.SSSXXX”格式的字符串转换为LocalDate - Convert String of this “yyyy-MM-dd'T'HH:mm:ss.SSSXXX” format to LocalDate
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM