如果在Java-11中使用ZonedDateTime在数据库中使用Datebse DateTime毫秒和纳秒,则默认将其截断为0

问题描述

我正在从Oracle数据库获取日期时间,并使用zoneddatetimejava-11中进行解析,如下所示:

  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](因此,认情况下,这里的0被截断。 但是,我的要求是像#1一样具有一致的固定长度o / p。)

期望的Java zoneddatetime o / p-> 2011-01-19T04:00:00.000000Z[UTC]

但是,我没有找到任何日期api方法来实现高于预期的o / p。除了操纵字符串,还有其他方法可以将尾随的0保留为固定长度。 我们在应用程序中具有一致的zoneddatetime类型,因此我们不希望更改它。

解决方法

我们在应用程序中具有一致的ZonedDateTime类型,因此我们没有 希望更改它。

您为什么认为2011-01-19T04:00Z[UTC]不一致?日期时间对象应该仅保留日期,时间和时区信息(并提供用于操作的方法/功能)。它不应该存储任何格式信息;否则,它将违反Single-responsibility principle。格式化应由格式化类处理,例如DateTimeFormatter(for modern date-time API),DateFormat(对于旧版java.util日期时间API)等。

每个类都应该重写toString()函数;否则,Object#toString将在其对象被打印时返回。 ZonedDateTime具有日期,时间和时区信息。下面给出了其toString()时间部分的实现方式:

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

如您所见,仅当第二部分和nano部分大于0时,它们才包含在返回的字符串中。这意味着如果要在输出字符串中使用这些(第二个和纳米)零,则需要使用格式设置类。下面是一个示例:

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

输出:

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

令人回味:

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

您期望从上面给出的代码中得到什么输出? 5.0代表与5.0000不同的值吗?您将如何打印5.0000? [提示:选中String#formatNumberFormatBigDecimal等。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...