Databse DateTime milli & nano seconds are truncated by default if its 0s while using it in java-11 using ZonedDateTime

混江龙づ霸主 提交于 2021-02-11 07:58:11

问题


I am fetching datetime from oracle db and parsing in java-11 using ZonedDateTime as below:

  1. oracle --> 1/19/2020 06:09:46.038631 PM

    java ZonedDateTime 0/p --> 2020-01-19T18:09:46.038631Z[UTC]

  2. oracle --> 1/19/2011 4:00:00.000000 AM

    java ZonedDateTime o/p --> 2011-01-19T04:00Z[UTC] (So, here the 0s are truncated by default. However, my requirement is to have consistent fixed length o/p like #1.)

expected java ZonedDateTime o/p --> 2011-01-19T04:00:00.000000Z[UTC]

However, I didnt find any date api methods to achieve above expected o/p. Instead of manipulating string, is there any way to preserve the trailing 0s with fixed length. We have consistent ZonedDateTime type in application, so we do not prefer to change that.


回答1:


We have consistent ZonedDateTime type in application, so we do not prefer to change that.

Why do you think 2011-01-19T04:00Z[UTC] is inconsistent? A date-time object is supposed to hold (and provide methods/functions to operate with) only the date, time, and time-zone information. It is not supposed to store any formatting information; otherwise, it will violate the Single-responsibility principle. The formatting should be handled by a formating class e.g. DateTimeFormatter (for modern date-time API), DateFormat (for legacy java.util date-time API) etc.

Every class is supposed to override the toString() function; otherwise, Object#toString will be returned when its object will be printed. A ZonedDateTime has date, time and time-zone information. Given below is how its toString() for time-part has been implemented:

@Override
public String toString() {
    StringBuilder buf = new StringBuilder(18);
    int hourValue = hour;
    int minuteValue = minute;
    int secondValue = second;
    int nanoValue = nano;
    buf.append(hourValue < 10 ? "0" : "").append(hourValue)
        .append(minuteValue < 10 ? ":0" : ":").append(minuteValue);
    if (secondValue > 0 || nanoValue > 0) {
        buf.append(secondValue < 10 ? ":0" : ":").append(secondValue);
        if (nanoValue > 0) {
            buf.append('.');
            if (nanoValue % 1000_000 == 0) {
                buf.append(Integer.toString((nanoValue / 1000_000) + 1000).substring(1));
            } else if (nanoValue % 1000 == 0) {
                buf.append(Integer.toString((nanoValue / 1000) + 1000_000).substring(1));
            } else {
                buf.append(Integer.toString((nanoValue) + 1000_000_000).substring(1));
            }
        }
    }
    return buf.toString();
}

As you can see, the second and nano parts are included in the returned string only when they are greater than 0. It means that you need to use a formatting class if you want these (second and nano) zeros in the output string. Given below is an example:

    import java.time.LocalDateTime;
    import java.time.ZoneOffset;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeFormatterBuilder;
    import java.util.Locale;

    public class Main {
        public static void main(String[] args) {
            String input = "1/19/2011 4:00:00.000000 AM";

            // Formatter for input string
            DateTimeFormatter inputFormatter = new DateTimeFormatterBuilder()
                                                .parseCaseInsensitive()
                                                .appendPattern("M/d/u H:m:s.n a")
                                                .toFormatter(Locale.ENGLISH);

            ZonedDateTime zdt = LocalDateTime.parse(input, inputFormatter).atZone(ZoneOffset.UTC);

            // Print `zdt` in default format i.e. the string returned by `zdt.toString()`
            System.out.println(zdt);

            // Formatter for input string
            DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.nnnnnnz");
            String output = zdt.format(outputFormatter);
            System.out.println(output);
        }
    }

Output:

2011-01-19T04:00Z
2011-01-19T04:00:00.000000Z

Food for thought:

public class Main {
    public static void main(String[] args) {
        double d = 5.0000;
        System.out.println(d);
    }
}

What output do you expect from the code given above? Does 5.0 represent a value different from 5.0000? How will you print 5.0000? [Hint: Check String#format, NumberFormat, BigDecimal etc.]



来源:https://stackoverflow.com/questions/63931623/databse-datetime-milli-nano-seconds-are-truncated-by-default-if-its-0s-while-u

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!