2121
2222import java .io .IOException ;
2323import java .math .BigDecimal ;
24+ import java .text .DecimalFormat ;
2425import java .text .SimpleDateFormat ;
2526import java .util .*;
2627
@@ -60,7 +61,7 @@ public final class DataWriterUtil {
6061 private static final String HOURS_OUTPUT_FORMAT = "%02d" ;
6162
6263 /**
63- * The format to output minutes in the the CSV format.
64+ * The format to output minutes in the CSV format.
6465 */
6566 private static final String MINUTES_OUTPUT_FORMAT = "%02d" ;
6667
@@ -81,6 +82,13 @@ public final class DataWriterUtil {
8182 */
8283 private static final List <String > TIME_FORMAT_STRINGS = Arrays .asList ("TIME" , "HHMM" );
8384
85+ /**
86+ * The format to store the percentage values. Appear in the data of
87+ * the {@link com.epam.parso.impl.SasFileParser.FormatAndLabelSubheader} subheader
88+ * and are stored in {@link Column#format}.
89+ */
90+ private static final String PERCENT_FORMAT = "PERCENT" ;
91+
8492 /**
8593 * The number of seconds in a minute.
8694 */
@@ -96,6 +104,12 @@ public final class DataWriterUtil {
96104 */
97105 private static final Locale DEFAULT_LOCALE = Locale .getDefault ();
98106
107+ /**
108+ * The format to output percentage values in the CSV format. This format is used
109+ * when {@link ColumnFormat#precision} does not contain the accuracy of rounding.
110+ */
111+ private static final DecimalFormat ZERO_PRECISION_FORMAT = new DecimalFormat ("0%" );
112+
99113 /**
100114 * These are sas7bdat format references to {@link java.text.SimpleDateFormat} date formats.
101115 * <p>
@@ -204,6 +218,8 @@ private static String processEntry(Column column, Object entry, Locale locale) t
204218 } else {
205219 if (TIME_FORMAT_STRINGS .contains (column .getFormat ().getName ())) {
206220 valueToPrint = convertTimeElementToString ((Long ) entry );
221+ } else if (PERCENT_FORMAT .equals (column .getFormat ().getName ())) {
222+ valueToPrint = convertPercentElementToString (entry , column .getFormat ());
207223 } else {
208224 valueToPrint = String .valueOf (entry );
209225 if (entry .getClass () == Double .class ) {
@@ -274,6 +290,24 @@ private static String convertDoubleElementToString(Double value) {
274290 return valueToPrint ;
275291 }
276292
293+ /**
294+ * The function to convert a percent element into a string. The accuracy of rounding
295+ * is stored in {@link Column#format}.
296+ * @param value the input numeric value to convert.
297+ * @param columnFormat the column format containing the precision of rounding the converted value.
298+ * @return the string with the text presentation of the input numeric value.
299+ */
300+ private static String convertPercentElementToString (Object value , ColumnFormat columnFormat ) {
301+ Double doubleValue = value instanceof Long ? ((Long ) value ).doubleValue () : (Double ) value ;
302+ DecimalFormat df = ZERO_PRECISION_FORMAT ;
303+ int precision = columnFormat .getPrecision ();
304+ if (precision != 0 ) {
305+ String pattern = "0%." + new String (new char [precision ]).replace ("\0 " , "0" );
306+ df = new DecimalFormat (pattern );
307+ }
308+ return df .format (doubleValue );
309+ }
310+
277311 /**
278312 * The function to remove trailing zeros from the decimal part of the numerals represented by a string.
279313 * If there are no digits after the point, the point is deleted as well.
0 commit comments