Похоже, что Котлин очень специфичен в отношении форматов даты. Я получаю строку в этом формате "Jan 1 2023 12:00AM" и хочу преобразовать ее в этот формат "2023-01-01 00:00:00.0". Я осмотрелся, но не смог найти решения.
fun FormatDateTime(dateTimeString: String): String{
val DATE_FORMAT = DateTimeFormatter.ofPattern("MMM dd uuuu")
var dat = dateTimeString.substring(0, dateTimeString.length-7).trim() //Removing ' 12:00AM' part
val changeDate = LocalDateTime.parse(dat, DATE_FORMAT)
//After getting the date, reformat it again to '2023-01-01 00:00:00.0'
return "" //return formatted date string, currently returning empty string
}
Но это провал. Ошибка следующая - java.time.format.DateTimeParseException: Text 'Jan 1 2023' could not be parsed at index 4. Есть ли способ добиться этого?
Внес некоторые изменения в ответ Слоу и не уверен, что это сломается, в каких сценариях, за исключением случаев, когда код выполняется в разных географических местах.
fun convert(input: String): String {
var sanitizedInput = input.replace("\\s+".toRegex(), " ").trim()
return LocalDateTime.parse(sanitizedInput, DateTimeFormatter.ofPattern("MMM d uuuu hh:mma"))
.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S"))
}
Добавлены комментарии и переименованы переменные для ясности.
Я не добавил ошибку, так как думаю, что есть лучший способ сделать это. Однако ошибка следующая: java.time.format.DateTimeParseException: текст «1 января 2023 г.» не удалось проанализировать по индексу 4.
Не забудьте указать локаль в форматтерах.
Я вставил исключение в вопрос. Нам будет легче понять вашу проблему и направить вас по правильному пути.
Время всегда 12 утра (12 ночи)? И должно ли время суток всегда быть 00:00:00.0 или это должно быть то же время суток, что и во входных данных?
Как правило, вам не следует хранить дату и время в строке и, следовательно, никогда не возникнет необходимости конвертировать строку одного формата в строку другого формата. Сохраните дату и время в формате ZonedDateTime, LocalDateTime или другом подходящем типе даты и времени. Когда вы получаете строковый ввод, немедленно анализируйте его. Если ваш вывод предназначен для вашей базы данных, не используйте для этого строку. Сохраните LocalDateTIme или OffsetDateTime через JDBC или JPA.
Также рекомендуется добавить Locale к вашему DateTimeFormatter (если вам необходимо его использовать), иначе формат будет зависеть от значения по умолчанию Locale, что может привести к неожиданным сценариям при анализе String, содержащих такие сокращения, как MMM.




Вы используете шаблон MMM dd uuuu для анализа входной строки. dd означает, что он ожидает, что дни, состоящие из одной цифры, будут дополнены ведущим 0. Но ваш пример ввода, Jan 1 2023 12:00AM, не имеет этого дополнения. Отсюда ошибка под индексом 4. Вам следует использовать d вместо dd.
Вам также следует рассмотреть возможность анализа всей входной строки вместо подстроки. Затем используйте truncatedTo API объекта LocalDateTime, чтобы установить время на ноль. Я предполагаю, что это то, что вам нужно, поскольку в настоящее время вы пытаетесь удалить значение времени из входной строки, а время вывода вашего примера — полночь.
Судя по вашему вопросу, следующий пример соответствует вашим потребностям:
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.time.temporal.ChronoUnit
import java.util.Locale
val INPUT_FORMAT = DateTimeFormatter.ofPattern("MMM d uuuu hh:mma", Locale.US)
val OUTPUT_FORMAT = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S", Locale.US)
fun main() {
val input = "Jan 1 2023 12:00AM"
println("$input => ${convert(input)}")
}
fun convert(input: String): String {
return LocalDateTime.parse(input, INPUT_FORMAT)
.truncatedTo(ChronoUnit.DAYS)
.format(OUTPUT_FORMAT)
}
Выход:
Jan 1 2023 12:00AM => 2023-01-01 00:00:00.0
Я явно указал локаль, чтобы локализуемые части входной строки («Январь», «AM»/«PM») правильно анализировались. Для примера я выбрал Locale.US, но вы можете использовать любую локаль, в которой используются правильные значения для MMM и a. Или даже позвольте локали определяться конфигурацией во время выполнения.
Вы можете положиться на языковой стандарт системы по умолчанию, но тогда ваш код, скорее всего, не будет работать на компьютерах с языковыми стандартами, отличными от вашего тестового компьютера.
Обратите внимание, что альтернативой truncatedTo(ChronoUnit.DAYS) является with(LocalTime.MIDNIGHT).
Хороший ответ, просто интересно. Я внес некоторые изменения в ваш код и получаю тот же результат со следующим кодом. Я знаю, что что-то может сломаться, но не знаю, что именно. Пожалуйста, посмотрите: fun Convert(input: String): String { var sanitizedInput = input.replace("\\s+".toRegex(), " ").trim() return LocalDateTime.parse(sanitizedInput, DateTimeFormatter.ofPattern( "МММ д уууу чч:мма")) .format(DateTimeFormatter.ofPattern("уууу-ММ-дд ЧЧ:мм:сс.С")) }
12:00AM то же самое, что 00:00:00.0. Так не является ли сокращение до целых дней риском выбросить время суток, которое мы хотели бы сохранить? В любом случае это не кажется необходимым.
@Anonymous Вопрос включает //Removing ' 12:00AM' part, но вывод примера все еще содержит 00:00:00.0, поэтому я предположил, что ОП хочет, чтобы время вывода всегда было 00:00:00.0, даже если время ввода отличается от 12:00AM.
Объясните, пожалуйста, для чего используется приемник
Stringи что такоеaVal. Кроме того, почему используется только длинаinput?