|
1 | 1 | /*
|
2 |
| - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. |
| 2 | + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. |
3 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
4 | 4 | *
|
5 | 5 | * This code is free software; you can redistribute it and/or modify it
|
|
121 | 121 | import java.util.regex.Matcher;
|
122 | 122 | import java.util.regex.Pattern;
|
123 | 123 |
|
| 124 | +import jdk.internal.util.DateTimeHelper; |
124 | 125 | import jdk.internal.util.DecimalDigits;
|
125 | 126 |
|
126 | 127 | import sun.text.spi.JavaTimeDateTimePatternProvider;
|
|
161 | 162 | * @since 1.8
|
162 | 163 | */
|
163 | 164 | public final class DateTimeFormatterBuilder {
|
164 |
| - |
165 | 165 | /**
|
166 | 166 | * Query for a time-zone that is region-only.
|
167 | 167 | */
|
@@ -3809,58 +3809,73 @@ public boolean format(DateTimePrintContext context, StringBuilder buf) {
|
3809 | 3809 | }
|
3810 | 3810 | long inSec = inSecs;
|
3811 | 3811 | int inNano = NANO_OF_SECOND.checkValidIntValue(inNanos != null ? inNanos : 0);
|
3812 |
| - // format mostly using LocalDateTime.toString |
| 3812 | + if (fractionalDigits == 0) { |
| 3813 | + inNano = 0; |
| 3814 | + } |
| 3815 | + boolean printNanoInLocalDateTime = fractionalDigits == -2 |
| 3816 | + || (inNano == 0 && (fractionalDigits == 0 || fractionalDigits == -1)); |
3813 | 3817 | if (inSec >= -SECONDS_0000_TO_1970) {
|
3814 |
| - // current era |
3815 |
| - long zeroSecs = inSec - SECONDS_PER_10000_YEARS + SECONDS_0000_TO_1970; |
3816 |
| - long hi = Math.floorDiv(zeroSecs, SECONDS_PER_10000_YEARS) + 1; |
3817 |
| - long lo = Math.floorMod(zeroSecs, SECONDS_PER_10000_YEARS); |
3818 |
| - LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, 0, ZoneOffset.UTC); |
3819 |
| - if (hi > 0) { |
3820 |
| - buf.append('+').append(hi); |
3821 |
| - } |
3822 |
| - buf.append(ldt); |
3823 |
| - if (ldt.getSecond() == 0) { |
3824 |
| - buf.append(":00"); |
3825 |
| - } |
| 3818 | + currentEra(buf, inSec, printNanoInLocalDateTime ? inNano : 0); |
3826 | 3819 | } else {
|
3827 |
| - // before current era |
3828 |
| - long zeroSecs = inSec + SECONDS_0000_TO_1970; |
3829 |
| - long hi = zeroSecs / SECONDS_PER_10000_YEARS; |
3830 |
| - long lo = zeroSecs % SECONDS_PER_10000_YEARS; |
3831 |
| - LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, 0, ZoneOffset.UTC); |
3832 |
| - int pos = buf.length(); |
3833 |
| - buf.append(ldt); |
3834 |
| - if (ldt.getSecond() == 0) { |
3835 |
| - buf.append(":00"); |
3836 |
| - } |
3837 |
| - if (hi < 0) { |
3838 |
| - if (ldt.getYear() == -10_000) { |
3839 |
| - buf.replace(pos, pos + 2, Long.toString(hi - 1)); |
3840 |
| - } else if (lo == 0) { |
3841 |
| - buf.insert(pos, hi); |
3842 |
| - } else { |
3843 |
| - buf.insert(pos + 1, Math.abs(hi)); |
3844 |
| - } |
3845 |
| - } |
| 3820 | + beforeCurrentEra(buf, inSec, printNanoInLocalDateTime ? inNano : 0); |
3846 | 3821 | }
|
3847 | 3822 | // add fraction
|
3848 |
| - if ((fractionalDigits < 0 && inNano > 0) || fractionalDigits > 0) { |
3849 |
| - buf.append('.'); |
3850 |
| - int div = 100_000_000; |
3851 |
| - for (int i = 0; ((fractionalDigits == -1 && inNano > 0) || |
3852 |
| - (fractionalDigits == -2 && (inNano > 0 || (i % 3) != 0)) || |
3853 |
| - i < fractionalDigits); i++) { |
3854 |
| - int digit = inNano / div; |
3855 |
| - buf.append((char) (digit + '0')); |
3856 |
| - inNano = inNano - (digit * div); |
3857 |
| - div = div / 10; |
3858 |
| - } |
| 3823 | + if (!printNanoInLocalDateTime) { |
| 3824 | + printNano(buf, inSec, inNano); |
3859 | 3825 | }
|
3860 | 3826 | buf.append('Z');
|
3861 | 3827 | return true;
|
3862 | 3828 | }
|
3863 | 3829 |
|
| 3830 | + private void printNano(StringBuilder buf, long inSec, int inNano) { |
| 3831 | + buf.append('.'); |
| 3832 | + int div = 100_000_000; |
| 3833 | + int fractionalDigits = this.fractionalDigits; |
| 3834 | + for (int i = 0; ((fractionalDigits == -1 && inNano > 0) || |
| 3835 | + (fractionalDigits == -2 && (inNano > 0 || (i % 3) != 0)) || |
| 3836 | + i < fractionalDigits); i++) { |
| 3837 | + int digit = inNano / div; |
| 3838 | + buf.append((char) (digit + '0')); |
| 3839 | + inNano = inNano - (digit * div); |
| 3840 | + div = div / 10; |
| 3841 | + } |
| 3842 | + } |
| 3843 | + |
| 3844 | + private static void currentEra(StringBuilder buf, long inSec, int inNano) { |
| 3845 | + long zeroSecs = inSec - SECONDS_PER_10000_YEARS + SECONDS_0000_TO_1970; |
| 3846 | + long hi = Math.floorDiv(zeroSecs, SECONDS_PER_10000_YEARS) + 1; |
| 3847 | + long lo = Math.floorMod(zeroSecs, SECONDS_PER_10000_YEARS); |
| 3848 | + LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, inNano, ZoneOffset.UTC); |
| 3849 | + if (hi > 0) { |
| 3850 | + buf.append('+').append(hi); |
| 3851 | + } |
| 3852 | + DateTimeHelper.formatTo(buf, ldt); |
| 3853 | + if (ldt.getSecond() == 0 && inNano == 0) { |
| 3854 | + buf.append(":00"); |
| 3855 | + } |
| 3856 | + } |
| 3857 | + |
| 3858 | + private static void beforeCurrentEra(StringBuilder buf, long inSec, int inNano) { |
| 3859 | + long zeroSecs = inSec + SECONDS_0000_TO_1970; |
| 3860 | + long hi = zeroSecs / SECONDS_PER_10000_YEARS; |
| 3861 | + long lo = zeroSecs % SECONDS_PER_10000_YEARS; |
| 3862 | + LocalDateTime ldt = LocalDateTime.ofEpochSecond(lo - SECONDS_0000_TO_1970, inNano, ZoneOffset.UTC); |
| 3863 | + int pos = buf.length(); |
| 3864 | + DateTimeHelper.formatTo(buf, ldt); |
| 3865 | + if (ldt.getSecond() == 0 && inNano == 0) { |
| 3866 | + buf.append(":00"); |
| 3867 | + } |
| 3868 | + if (hi < 0) { |
| 3869 | + if (ldt.getYear() == -10_000) { |
| 3870 | + buf.replace(pos, pos + 2, Long.toString(hi - 1)); |
| 3871 | + } else if (lo == 0) { |
| 3872 | + buf.insert(pos, hi); |
| 3873 | + } else { |
| 3874 | + buf.insert(pos + 1, Math.abs(hi)); |
| 3875 | + } |
| 3876 | + } |
| 3877 | + } |
| 3878 | + |
3864 | 3879 | @Override
|
3865 | 3880 | public int parse(DateTimeParseContext context, CharSequence text, int position) {
|
3866 | 3881 | // new context to avoid overwriting fields like year/month/day
|
|
0 commit comments