Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

377
Views
¿Cómo analizar cadenas de fecha y hora y zona horaria con dígitos árabes-hindúes en Java 8?

Quería analizar la cadena de fecha y hora y la zona horaria con dígitos árabes-hindúes, así que escribí un código como este:

 String dateTime = "٢٠٢١-١١-٠٨T٠٢:٢١:٠٨+٠٢:٠٠"; char zeroDigit = '٠'; Locale locale = Locale.forLanguageTag("ar"); DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX") .withLocale(locale) .withDecimalStyle(DecimalStyle.of(locale).withZeroDigit(zeroDigit)); ZonedDateTime parsedDateTime = ZonedDateTime.parse(dateTime, pattern); assert parsedDateTime != null;

Pero recibí la excepción:

java.time.format.DateTimeParseException: el texto '٢٠٢١-١١-٠٨T٠٢:٢١:٠٨+٠٢:٠٠' no se pudo analizar en el índice 19

Revisé muchas preguntas en Stackoverflow, pero todavía no entiendo qué hice mal.

Funciona bien con dateTime = "٢٠٢١-١١-٠٨T٠٢:٢١:٠٨+02:00" cuando la zona horaria no usa dígitos árabes-hindúes.

over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

Su cadena de fecha y dateTime es incorrecta, mal entendida. Obviamente intenta ajustarse al formato ISO 8601 y falla. Porque el formato ISO 8601 usa dígitos US-ASCII.

Las clases de java.time ( Instant , OffsetDateTime y ZonedDateTime ) analizarían su cadena sin ningún formateador si solo los dígitos fueran correctos para ISO 8601. En la gran mayoría de los casos, tomaría su camino: intente analizar la cadena tal como es . No en este caso. Para mí tiene más sentido corregir la cadena antes de analizarla.

 String dateTime = "٢٠٢١-١١-٠٨T٠٢:٢١:٠٨+٠٢:٠٠"; char[] dateTimeChars = dateTime.toCharArray(); for (int index = 0; index < dateTimeChars.length; index++) { if (Character.isDigit(dateTimeChars[index])) { int digitValue = Character.getNumericValue(dateTimeChars[index]); dateTimeChars[index] = Character.forDigit(digitValue, 10); } } OffsetDateTime odt = OffsetDateTime.parse(CharBuffer.wrap(dateTimeChars)); System.out.println(odt);

Producción:

2021-11-08T02:21:08+02:00

Editar: será aún mejor, por supuesto, si puede educar al editor de la cadena para que use dígitos US-ASCII.

Editar: sé que el artículo de Wikipedia al que enlazo a continuación dice:

Las representaciones deben escribirse en una combinación de números arábigos y los caracteres informáticos específicos (como "-", ":", "T", "W", "Z") a los que se asignan significados específicos dentro del estándar; …

Esta es una causa imaginable de la confusión. El artículo Números arábigos vinculado a dice:

Los números arábigos son los diez dígitos: 0, 1, 2, 3, 4, 5, 6, 7, 8 y 9.

Editar: cómo convierto cada dígito: Character.getNumericValue() convierte de un char que representa un dígito a un int igual al número que representa el dígito, por lo que '٠' a 0, '٢' a 2, etc. Funciona para todos los caracteres que son dígitos (no solo los árabes y ASCII). Character.forDigit() realiza una especie de conversión opuesta, solo que siempre a US ASCII, por lo que 0 a '0' , 2 a '2' , etc.

Editar: gracias a @Holger por llamar mi atención sobre CharBuffer en este contexto. Un CharBuffer implementa CharSequence , el tipo que requieren los métodos de parse de java.time, por lo que nos evita convertir la matriz char de nuevo en String .

Enlaces

  • Artículo de Wikipedia: ISO 8601
  • Artículo de Wikipedia: números arábigos
over 4 years ago · Santiago Trujillo Report

0

El mensaje de error indica que el problema está en el índice 19 en la cadena de entrada.

El carácter 19 es el carácter + en su cadena de entrada. Esto significa que el desplazamiento (representado por XXX en su patrón) no se puede analizar.

El problema no es el + en sí mismo. El problema es que las compensaciones de zona horaria, como +05:00 , nunca se localizan.

La documentación no habla de esto, así que tuve que ir al código fuente de DateTimeFormatterBuilder para verificarlo.

Dentro de esa clase está esta clase interna :

 static final class OffsetIdPrinterParser implements DateTimePrinterParser {

En esa clase, podemos encontrar un método de análisis que tiene llamadas a los métodos privados parseHour , parseMinute y parseSeconds .

Cada uno de esos métodos se delega a un método parseDigits privado. En ese método, podemos ver que solo se consideran dígitos ASCII :

 char ch1 = parseText.charAt(pos++); char ch2 = parseText.charAt(pos++); if (ch1 < '0' || ch1 > '9' || ch2 < '0' || ch2 > '9') { return false; }

Entonces, la respuesta aquí es que el desplazamiento de la zona horaria debe consistir en dígitos ASCII, independientemente de la configuración regional.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!