1 /* Copyright 2002-2024 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.utils;
18
19 import java.util.Locale;
20
21 import org.hipparchus.util.RyuDouble;
22
23 /** Formatter used to produce strings from data with high accuracy.
24 * <p>
25 * When producing test output from computed data, we want the shortest
26 * decimal representation of a floating point number that maintains
27 * round-trip safety. That is, a correct parser can recover the exact
28 * original number.
29 * </p>
30 * <p>
31 * For efficiency, this class uses the {@link RyuDouble Ryƫ} algorithm
32 * for producing shortest string representation with round-trip safety.
33 * </p>
34 * @author Luc Maisonobe
35 * @since 11.0
36 */
37 public class AccurateFormatter {
38
39 /**
40 * Standardized locale to use, to ensure files can be exchanged without
41 * internationalization issues.
42 */
43 public static final Locale STANDARDIZED_LOCALE = Locale.US;
44
45 /** String format used for dates. **/
46 private static final String DATE_FORMAT = "%04d-%02d-%02dT%02d:%02d:%s";
47
48 /** Low switch level for exponential format in dates (will never be reached due to {@link #LOW_TRUNCATION}). */
49 private static final int LOW_EXP = -18;
50
51 /** Truncation level for seconds, to avoid scientific format). */
52 private static final double LOW_TRUNCATION = 1.0e-15;
53
54 /** Private constructor for a utility class.
55 */
56 private AccurateFormatter() {
57 // nothing to do
58 }
59
60 /** Format a double number.
61 * @param value number to format
62 * @return number formatted to full accuracy
63 */
64 public static String format(final double value) {
65 return RyuDouble.doubleToString(value);
66 }
67
68 /** Format a date.
69 * @param year year
70 * @param month month
71 * @param day day
72 * @param hour hour
73 * @param minute minute
74 * @param seconds seconds
75 * @return date formatted to full accuracy
76 */
77 public static String format(final int year, final int month, final int day,
78 final int hour, final int minute, final double seconds) {
79 final double truncated = seconds < LOW_TRUNCATION ? 0.0 : seconds;
80 final String s = RyuDouble.doubleToString(truncated, LOW_EXP, RyuDouble.DEFAULT_HIGH_EXP);
81 return String.format(STANDARDIZED_LOCALE, DATE_FORMAT,
82 year, month, day,
83 hour, minute, s.charAt(1) == '.' ? "0" + s : s);
84 }
85
86 }