Java 8 форматирование и парсинг

Цикл статей «Учебник Java 8».

Следующая статья — «Java 8 консоль».
Предыдущая статья — «Java 8 дата и время».

В мире огромное количество различных языков, религий, культур и стран. В каждой стране и в каждом языке зачастую приняты свои формы записи чисел, дат и денежных единиц. Локализация приложения в конкретной стране — это далеко не самый тривиальный процесс, подразумевающий не только перевод на язык страны, но и запись чисел и дат в формате, принятом в этой стране, удаление иконок и изображений, нарушающих законодательство этой страны и т. д.

Например, в в русском языке принята следующая запись дат:

12.01.2016 — двенадцатое января две тысячи шестнадцатого года

10 июня 2016 — 10 июня 2016 года.

Но если мы локализуем приложение в США, то даты будут выглядеть так:

01/12/2016 — the twelfth of January year twenty sixteen

June 10, 2016 — the tenth of June year twenty sixteen

С записью чисел тоже всё далеко не так просто. Вот числа для русского языка:

10 000 000,34

3 454,456

А вот те же числа для США:

10,000,000.34

3,454.456

Все современные языки поддерживают конвертацию дат и числовых переменных в строку и обратно в соответствии с указанными региональными настройками (локалью) или региональными настройками по умолчанию.

Для понимания дальнейшего текста статьи рекомендуется ознакомиться с классом java.util.Locale, представляющего собой локаль (региональные настройки).

Вы можете получить экземпляр текущей локали с помощью кода:

java.text.NumberFormat

Класс java.text.NumberFormat предназначен для форматирования и парсинга чисел. Это абстрактный класс, экземпляры которого можно получить с помощью методов getInstance():

 

Полученный экземпляр NumberFormat  можно использовать для форматирования чисел с помощью метода format  и парсинга чисел с помощью метода parse:

Пример:

Результат:

java.text.DecimalFormat

Класс java.text.DecimalFormat расширяет класс java.text.NumberFormat. Класс DecimalFormat  предназначен специально для работы с десятичными числами. Он поддерживает различные типы чисел: проценты, денежные единицы и т. д.

Все методы format  и parse, способ создания аналогичны NumberFormat.

Класс DecimalFormat  дополнительно содержит настройку:

позволяющую методу parse  возвращать экземпляры BigDecimal .

Класс java.text.DecimalFormat содержит два дополнительных конструктора, принимающих строку с форматом числа:

Метод, принимающий DecimalFormatSymbols, позволяет полностью настроить форматирование числа. Строка pattern  содержит шаблон вида "0.00"  может содержать следующие специальные символы:

Спец. символ Значение
Число
# Число, незначащие нули не показываются
. Разделитель дробной и целой части
- Знак минуса
, Разделитель групп
E Разделяет мантиссу и экспоненту в научной записи. В префиксе или в суффиксе нужно заключать в кавычки.
; Разделяет положительный шаблон числа и отрицательный шаблон числа
% Умножается на 100 и показывается в процентах
\u2030 Умножается на 1 000 и показывается как в милях
¤ (\u00A4) Денежный знак. Заменяется денежный символом локали. Если задвоен, то указывается международный денежный символ. Если указан, то используется разделитель денег вместо разделителя дробной и целой части
' Кавычки. "'#'#" преобразует 123 в "#123" . Чтобы записать саму одинарную кавычку, используйте две одинарные кавычки.

Пример:

Результат:

java.text.DateFormat

Класс java.text.DateFormat предназначен для форматирования дат. Получить экземпляр этого класса можно с помощью одного из методов:

 

Если нужно форматировать/парсить только дату без времени, то нужно использовать один из следующих методов:

Здесь style  может быть одно из значений: DateFormat.FULL, DateFormat.LONG, DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.DEFAULT.

 

Если нужно форматировать/парсить только время, то нужно использовать один из методов:

Здесь style  может быть одно из значений: DateFormat.FULL, DateFormat.LONG, DateFormat.SHORT, DateFormat.MEDIUM, DateFormat.DEFAULT.

 

Если нужно форматировать/парсить дату с временем, то нужно использовать один из методов:

 

Форматирование и парсинг также происходит с помощью методов format  и parse . Пример:

 

java.text.SimpleDateFormat

Класс java.text.SimpleDateFormat наследуется от java.text.DateFormat  и позволяет указать пользовательский шаблон форматирования.

Конструкторы:

Конструктор с DateFormatSymbols позволяет создать форматировщик, используя особые правила.

Шаблон pattern  может содержать следующие специальные символы:

Буква Компонент даты и времени Представление Примеры
G  Эра Text AD
y  Год Year 1996; 96
Y  Год Year 2009; 09
M  Месяц в году (зависит от контекста) Month July; Jul; 07
L  Месяц в году (самостоятельная форма) Month July; Jul; 07
w  Неделя в годе Number 27
W  Неделя в месяце Number 2
D  День в году Number 189
d  День в месяце Number 10
F  День недели в месяце Number 2
E  Название дня недели Text Tuesday; Tue
u  Номер дня недели (1 = Понедельник, …, 7 = Воскресенье) Number 1
a  Am/pm Text PM
H  Час в дне (0-23) Number 0
k  Час в дне (1-24) Number 24
K  Час в дне am/pm (0-11) Number 0
h  Час в дне am/pm (1-12) Number 12
m  Минуты Number 30
s  Секунды Number 55
S  Миллисекунды Number 978
z  Часовой пояс General time zone Pacific Standard Time; PST; GMT-08:00
Z  Часовой пояс RFC 822 time zone -0800
X  Часовой пояс ISO 8601 time zone -08; -0800; -08:00

Описание столбца «представление»:

  • Text: Если в шаблоне 4 буквы или более, то используется полная форма, в противном случае используется сокращённая форма. При парсинге принимаются обе формы, независимо от количества букв в шаблоне.
  • Number: Количество букв в шаблоне — это минимальное количество цифр, более короткие числа добиваются нулями. При парсинге количество букв игнорируется, если только оно не требуется для разделения соседних полей.
  • Year: Если Calendar  форматировщика является григорианским календарём, то применяются следующие правила. При форматировании если количество букв равно двум, то год усекается до двух цифр, в противном случае интерпретируется как число. При парсинге если количество букв больше двух, то год интерпретируется буквально, независимо от количества цифр. Поэтому использование шаблона "MM/dd/yyyy"  и строки "01/11/12"  получается 11 января 12 года нашей эры. При парсинге с сокращённой формой года ( "y"  или "yy" ) SimpleDateFormat  интерпретирует сокращённый год относительно какого-либо века. Он выравнивает даты так, чтобы они были в диапазоне от 80 лет до даты создания SimpleDateFormat  и до 20 лет после даты создания SimpleDateFormat. Во время парсинга только строки, состоящие строго из двух цифр интерпретируются в текущий век. Любые другие числовые строки, состоящие из одной цифры или трёх и более, интерпретируются как полный год.
  • Month: Если количество букв в шаблоне равно 3 или более, то месяц интерпретируется как текст, в противном случае интерпретируется как число. Буква M  создаёт имена месяцев, зависимые от контекста. Если в конструктор был передан DateFormatSymbols  или был использован метод setDateFormatSymbols, то имена месяцев берутся из DateFormatSymbols. Буква L  создаёт самостоятельную форму имён месяцев.
  • /a>General time zone: Часовые пояса интерпретируются по текстовым именам. При использовании смещения часовой пояс указывается в виде GMT +01:30 или GMT-12:33.
  • RFC 822 time zone: Используются четыре цифры: -0800 или +1200.
  • ISO 8601 time zone: Используются две цифры, четыре цифры, или с разделением часов и минут двоеточием: -08; -0800; -08:00.

java.io.PrintStream

Класс java.io.PrintStream позволяет писать форматированные данные в любой поток. Вам вряд ли когда-нибудь придётся создавать экземпляры этого класса вручную, гораздо чаще вы будете использовать готовые классы, вроде возвращаемых System.out. PrintStream  имеет методы print  и println, перегруженные для любого примитивного типа и для класса Object  (в этом случае используется его метод toString() ).

Класс PrintStream  никогда не бросает IOException, вместо этого он устанавливает свой внутренний флаг, который может быть проверен с помощью метода public boolean checkError().

Особое внимание заслуживают методы:

Эти методы позволяют писать в поток форматированные данные. Здесь format  — это шаблон строки, который подробно в пункте «java.util.Formatter».

java.util.Formatter

Класс java.util.Formatter используется во всех методах, принимающих строку форматирования: java.io.PrintStream.format , System.out.format, String.format  и т. д.

Каждый метод, принимающий строку форматирования, нуждается в шаблоне и списке аргументов. Пример:

Строка форматирования является первым аргументом метода format. Она содержит три спецификатора формата: "%1$tm", "%1$te"  и "%1$tY", которые указывают на способ обработки аргументов, и как они будут вставлены в текст. Остальные части строки содержат фиксированный текст, включающий в себя "Dukes Birthday: "  и любые другие пробелы и знаки препинания. Список аргументов состоит из всех аргументов, переданных в метод после строки форматирования. В примере выше список аргументов содержит только один объект java.util.Calendar.

Спецификаторы формата для общих, символьных и числовых типов имеют следующий синтаксис:

Необязательный argument_index  показывает позицию аргумента в списке аргументов. К первому аргументу ссылаются "1$", ко второму "2$", нумерация аргументов начинается с единицы.

Необязательный flags  — это набор символов, модифицирующих выходной формат. Допустимый набор символов зависит от conversion.

Необязательный width  — это положительное десятичное число, указывающее минимальное количество символов, которое будет записано в выходную строку.

Необязательный precision  — это неотрицательное десятичное число, обычно используемое для ограничения количества символов. Поведение precision  зависит от conversion.

Обязательное conversion  — это символ, указывающий на способ форматирования аргумента. Допустимый набор символов зависит от типа аргумента.

Спецификаторы форматов, используемые для дат и времени, имеют следующий синтаксис:

Бывают следующие виды conversion:

  • General — может быть применён к любому типу аргумента.
  • Character — может быть применён к базовым типам, представляющим символы Юникода: char, Character, byte, Byte, short, Short. Этот тип conversion  может быть также применён к типам int  и Integer, если Character.isValidCodePoint(int)  возвращает true.
  • Integral — может быть применён к любому целочисленному типу Java: byte, Byte, short, Short, int, Integer, long, Long, BigInteger  (но не к char  или Character).
  • Floating point — может быть применён к типам с плавающей точкой: float, Float, double, Double  и BigDecimal.
  • Date/Time — может быть применён к типам Java, которые могут содержать дату или время: long, Long, Calendar, Date  или TemporalAccessor.
  • Percent — создаёт литеру '%'  ( '\u0025' ).
  • Line separator — специфичный для платформы разделитель строк.

Следующая таблица содержит поддерживаемые conversion. Заглавные буквы имеют то же значение, что и прописные, но результат преобразуется в верхнему регистру с помощью String.toUpperCase().

Conversion Категория аргумента Описание
'b''B' general Если аргумент null, то результат "false". Если аргумент  boolean  или Boolean, то результатом будет результат вызова String.valueOf(arg). В противном случае результат "true".
'h''H' general Если аргумент null, то результатом будет "null". В противном случае результат получается вызовом Integer.toHexString(arg.hashCode()).
's''S' general Если аргумент null, то результат "null". Если аргумент реализует интерфейс java.util.Formattable, то вызывается метод arg.formatTo. В противном случае результат получается вызовом arg.toString().
'c''C' character Результатом будет символ юникода.
'd'  integral Результат форматируется как десятичное целое.
'o'  integral Результат форматируется как восьмиричное целое.
'x''X' integral Результат форматируется как шестнадцатеричное целое.
'e''E' floating point Результат форматируется как десятичное число в научной записи.
'f'  floating point Результат форматируется как десятичное число.
'g''G' floating point Результат форматируется используя научную запись или десятичный формат в зависимости от точости и значения после округления.
'a''A' floating point Результат форматируется в шестнадцатеричное число с плавающей точкой, мантиссой и показателем степени. Не поддерживается для java.math.BigDecimal.
't''T' date/time Префикс для даты и времени.
'%'  percent Результатом будет символ   '%'  ( '\u0025' )
'n'  line separator Разделитель линий, принятой в текущей платформе.

Следующие символы используются в качестве суффиксов к 't'  и 'T'  и используются для дат и времени:

Для форматирования времени:

'H'  Час в 24-часовом дне. Форматируется как две цифры с предваряющим нулём, если нужно, то есть 00 - 23.
'I'  Час от единицы до двенадцати. Форматируется как две цифры с предваряющим нулём, если нужно, то есть 01 - 12.
'k'  Час в 24-часовом дне, 0 - 23.
'l'  Час от единицы до двенадцати, 1 - 12.
'M'  Минуты в часе. Форматируются как две цифры с предваряющим нулём, если нужно, то есть 00 - 59.
'S'  Секунды в минуте, форматируются как две цифры с предваряющим нулём, если нужно, то есть 00 - 60 ( "60"  — специальное значение, необходимое для поддержки секунды координации).
'L'  Миллисекунды в секунде. Форматируются как три цифры с предваряющими нулями, если нужно, то есть  000 - 999.
'N'  Наносекунды в секунде. Форматируются как девять цифр с предваряющими нулями, если нужно, то есть 000000000 - 999999999.
'p'  До обеда или поле обеда ( "am"  или "pm" ). Используйте префикс 'T', чтобы результат был в верхнем регистре.
'z'  RFC 822 смещение часовой зоны от GMT, например -0800. Это значение выравнивается для учёта перехода на зимнее/летнее время. Для long, Long, Date  используется часовой пояс по умолчанию для текущего экземпляра виртуальной машины Java.
'Z'  Строка, содержащая абревиатуру часового пояса. Это значение выравнивается, чтобы учеть переход на зимнее/летнее время. Для long, Long, Date  используется часовой пояс по умолчанию для текущего экземпляра виртуальной машины Java.
's'  Секунды с начала эпохи от 1 января 1970 года 00:00:00 UTC. От  Long.MIN_VALUE/1000  до Long.MAX_VALUE/1000.
'Q'  Миллисекунды с начала эпохи 1 января 1970 года 00:00:00 UTC. От   Long.MIN_VALUE  до Long.MAX_VALUE .

Для форматирования дат:

'B'  Полное имя месяца в соответствии с региональными настройками, например "январь", "февраль", "January", "February".
'b'  Сокращённое имя месяца в соответствии с региональными настройками, например "янв", "фев", "Jan", "Feb".
'h'  То же что и  'b'.
'A'  Полное имя дня недели в соответствии с региональными настройками, например "воскресенье", "понедельник", "Sunday", "Monday".
'a'  Короткое название дня недели в соответствии с региональными настройками, например "Пн", "Вт", "Sun""Mon".
'C'  Четыре цифры года, поделённые на 100, и форматированные как две цифры с предваряющим нулём, если нужно 00 - 99.
'Y'  Год, форматированный как минимум четырьмя цифрами с предваряющим нулём, если нужно, то есть 0092 равен 92 CE для григорианского календаря.
'y'  Последние две цифры года, форматированные с предваряющим нулём, если необходимо, то есть 00 - 99.
'j'  День года, форматированный как три цифры с предваряющими нулями, если необходимо, то есть  001 - 366 для григорианского календаря.
'm'  Месяц, форматированный двумя цифрами с предваряющим нулём, если необходимо, то есть 01 - 13.
'd'  День месяца, форматированный как две цифры с предваряющими нулями, если необходимо, то есть 01 - 31
'e'  День в месяце, форматированный как две цифры, то есть  1 - 31.

Для форматирования наиболее часто используемых сочетаний дат и времени:

'R'  Время 24-часовой день  "%tH:%tM"
'T'  Время в формате "%tH:%tM:%tS".
'r'  Время в формате "%tI:%tM:%tS %Tp".
'D'  Дата в формате "%tm/%td/%ty".
'F'  ISO 8601 форматированная дата "%tY-%tm-%td".
'c'  Дата и время в формате "%ta %tb %td %tT %tZ %tY".

Поддерживаемые флаги:

Флаг General Character Integral Floating Point Date/Time Описание
'-' y y y y y Результат будет выровнен по левому краю.
'#' y1 y3 y Результат должен использовать альтернативну форму, зависимую от conversion.
'+' y4 y Результат всегда будет содержать знак.
' ' y4 y Результат будет содержать лидирующий пробел для положительых значений.
'0' y y Результа будет выровнен нулями.
',' y2 y5 Результат будет содержать разделители групп указанной локали.
'(' y4 y5 Результат будет заключать отрицательные значения в скобки.

1 Зависит от определения  Formattable.

2 Только для conversion  'd' .

3 Только для conversion 'o', 'x' и  'X'.

4 Для conversion 'd', 'o', 'x' и  'X', примененных к java.math.BigInteger, или  'd' , применённой к byte, Byte, short, Short, int, Integer, long, Long.

5 Только для conversion 'e' , 'E' , 'f' , 'g' и 'G'.

width  указывает минимальное количество символов, которые будут записаны в выходную строку. Для разделителя линий width  не применяется.

precision  указывает максимальное количество символов, которые будут записаны в выходную строку. Для conversion  'a', 'A', 'e', 'E', 'f'  precision  — количество символов после точки. Если conversion  равен 'g'  или 'G', то precision  указывает общее количество значимых чисел после округления. Для character, integral, date/time, percent, line separator этот параметр не указывается.

argument index  — десятичное число, указывающее позицию аргумента в списке аргументов. Первый аргумент "1$", второй "2$"  и т. д. Можно использовать флаг '<'  ( '\u003c' ), который использует ещё раз предыдущий аргумент:

java.util.Scanner

Класс java.util.Scanner предназначен для разбиения форматированного ввода на токены и конвертирования токенов в соответствующий тип данных.

По умолчанию сканер использует пробельные символы (пробелы, табуляторы, разделители линий) для разделения токенов. Рассмотрите следующий код:

Если файл «xanadu.txt» содержит следующий текст:

То результатом работы программы будет вывод:

Чтобы использовать другой разделитель токенов используйте метод useDelimiter, в который передаётся регулярное выражение. Например, предположим, что мы хотим использовать в качестве разделителя запятую, после которой может идти, а может не идти пробел:

Класс java.util.Scanner  поддерживает все примитивные типы Java, java.math.BigInteger  и java.math.BigDecimal. Scanner  использует экземпляр java.util.Locale  для преобразования строк в эти типы данных. Пример:

Цикл статей «Учебник Java 8».

Следующая статья — «Java 8 консоль».
Предыдущая статья — «Java 8 дата и время».

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *