Преобразовать строку в дату и удалить значение дня (всегда устанавливается 1 день месяца)
Я могу преобразовать String
к Date
:
private static final SimpleDateFormat CARD_DATE_FORMAT = new SimpleDateFormat("yyMMdd", Locale.getDefault());
public static Date toCardDateFormat(String date){
try {
return CARD_DATE_FORMAT.parse(date);
} catch (ParseException e) {
return null;
}
}
Например у меня 200908
- он будет преобразован в 2020-09-08
, но мне нужно установить день всегда 1-го числа месяца. я нуждаюсь 2020-09-01
, Как я могу сделать это?
5 ответов
В соответствии с вашими потребностями вы можете использовать этот метод:
private static final SimpleDateFormat CARD_DATE_FORMAT = new SimpleDateFormat("yyMMdd", Locale.getDefault());
public static String toCardDateFormat(String date) {
try {
Date value = CARD_DATE_FORMAT.parse(date);
SimpleDateFormat dateFormatter = new SimpleDateFormat("yy-MM", Locale.getDefault());
String datetimeLocale = dateFormatter.format(value);
String newDate = datetimeLocale + "-01";
return newDate;
} catch (ParseException e) {
return null;
}
}
для объекта даты вы можете использовать это:
public static Date toCardDateFormat(String date) {
try {
Date value = CARD_DATE_FORMAT.parse(date);
SimpleDateFormat dateFormatter = new SimpleDateFormat("yy-MM", Locale.getDefault());
String datetimeLocale = dateFormatter.format(value);
String newDate = datetimeLocale + "-01";
SimpleDateFormat dateFormat = new SimpleDateFormat("yy-MM-dd",Locale.getDefault());
Date d = dateFormat.parse(newDate);
return d;
} catch (ParseException e) {
return null;
}
}
- В вашем коде есть проблема с многопоточностью, лучше избегайте ее локального создания в функции преобразования (иначе у вас будут проблемы с многопоточностью, так как этот класс не является поточно-ориентированным)
Ответ на ваш вопрос (используя ols Date api) - вы можете использовать Календарь, чтобы сделать это:
public static Date toCardDateFormat(String date){
Date result = null;
try {
result = new SimpleDateFormat("yyMMdd", Locale.getDefault()).parse(date);
} catch (ParseException e) {
return null; // or better throw exception or return Optional.empty()
}
Calendar cal = Calendar.getInstance();
cal.setTime(result);
cal.set(Calendar.DAY_OF_MONTH, 1);
return cal.getTime();
}
Maciej ответит правильно, но если вы используете Java 8 или выше, лучше использовать классы java.time:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMdd");
// parse and change the day of month
LocalDate d = LocalDate.parse("200908", formatter).withDayOfMonth(1);
System.out.println(d); // 2020-09-01
Обратите внимание, что LocalDate
печатается в формате, который вы хотите - который соответствует ISO8601. Если вы хотите другой формат, просто используйте другой DateTimeFormatter
и позвонить format
метод.
Изменение строки вручную, как предлагают другие, также может сработать, но если вы имеете дело с датами, почему бы не использовать правильный API для обработки дат? Прямое манипулирование строками не поможет вам в таких случаях, как недопустимые даты (средство форматирования выдаст исключение для недопустимых входных данных) или если вы попытаетесь изменить день на недопустимые значения (например, день 31 для апреля или 29 для февраля в не високосный год, который проверяется API и выдает исключение, если значение недопустимо).
private static final DateTimeFormatter CARD_DATE_FORMAT
= DateTimeFormatter.ofPattern("yyMMdd", Locale.getDefault());
public static Optional<YearMonth> toCardDateFormat(String date) {
try {
return Optional.of(YearMonth.parse(date, CARD_DATE_FORMAT));
} catch (DateTimeParseException e) {
return Optional.empty();
}
}
Не возвращайся null
из метода. Риск NullPointerException
на стороне звонящего было бы здорово. Если вы считаете, что не возвращать значение - это правильно, если строка в неправильном формате или содержит недопустимую дату, используйте Optional
заставить вызывающего абонента принять во внимание возможность невозврата значения. Другой очевидный вариант - оставить любое исключение при разборе вызывающей стороне:
public static YearMonth toCardDateFormat(String date) {
return YearMonth.parse(date, CARD_DATE_FORMAT);
}
DateTimeParseException
является непроверенным исключением, поэтому его не нужно объявлять в сигнатуре метода. Давай попробуем:
System.out.println(toCardDateFormat("200908"));
Это печатает:
2020-09
Другие сообщения:
- Я использую и горячо рекомендую java.time, современный Java-интерфейс даты и времени. Старые классы даты и времени из Java 1.0 и 1.1 теперь давно устарели, и
SimpleDateFormat
в частности это общеизвестно хлопотно. Я думаю, что вы должны избегать их. С современным API гораздо приятнее работать. - Кажется, вы бы действительно предпочли убрать день месяца, чтобы у вас были только месяц и год?
YearMonth
класс из java.time делает именно это для вас. Если вместо этого вам нужна полная дата, используйтеLocalDate
класс как в ответе хунтов.
Ссылка: Oracle, учебник: Дата и время, объясняющие, как использовать java.time
,
Вы можете попробовать что-то вроде этого:
String[] arr = date.split("-");
String newDate = arr[0] + "-" + arr[1] + "-01";