java - example - ¿Cómo formatea el día del mes para decir "11 °", "21 °" o "23 °"(indicador ordinal)?
java dateformat constants (16)
Sé que esto me dará el día del mes como número ( 11
, 21
, 23
):
SimpleDateFormat formatDayOfMonth = new SimpleDateFormat("d");
¿Pero cómo formatear el día del mes para incluir un indicador ordinal , por ejemplo, 11th
, 21st
o 23rd
?
El único problema con la solución provista por Greg es que no cuenta para un número mayor a 100 con el final de los números "adolescentes". Por ejemplo, 111 debería ser 111º, no 111º. Esta es mi solución:
/**
* Return ordinal suffix (e.g. ''st'', ''nd'', ''rd'', or ''th'') for a given number
*
* @param value
* a number
* @return Ordinal suffix for the given number
*/
public static String getOrdinalSuffix( int value )
{
int hunRem = value % 100;
int tenRem = value % 10;
if ( hunRem - tenRem == 10 )
{
return "th";
}
switch ( tenRem )
{
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
El siguiente método se puede usar para obtener la cadena formateada de la fecha que se le pasa. Formateará la fecha para decir 1st, 2nd, 3rd, 4th .. usando SimpleDateFormat en Java. por ejemplo: - 1 de septiembre de 2015
public String getFormattedDate(Date date){
Calendar cal=Calendar.getInstance();
cal.setTime(date);
//2nd of march 2015
int day=cal.get(Calendar.DATE);
switch (day % 10) {
case 1:
return new SimpleDateFormat("d''st'' ''of'' MMMM yyyy").format(date);
case 2:
return new SimpleDateFormat("d''nd'' ''of'' MMMM yyyy").format(date);
case 3:
return new SimpleDateFormat("d''rd'' ''of'' MMMM yyyy").format(date);
default:
return new SimpleDateFormat("d''th'' ''of'' MMMM yyyy").format(date);
}
En kotlin puedes usar esto
fun changeDateFormats(currentFormat: String, dateString: String): String {
var result = ""
try {
val formatterOld = SimpleDateFormat(currentFormat, Locale.getDefault())
formatterOld.timeZone = TimeZone.getTimeZone("UTC")
var date: Date? = null
date = formatterOld.parse(dateString)
val dayFormate = SimpleDateFormat("d", Locale.getDefault())
var day = dayFormate.format(date)
val formatterNew = SimpleDateFormat("hh:mm a, d''" + getDayOfMonthSuffix(day.toInt()) + "'' MMM yy", Locale.getDefault())
if (date != null) {
result = formatterNew.format(date)
}
} catch (e: ParseException) {
e.printStackTrace()
return dateString
}
return result
}
private fun getDayOfMonthSuffix(n: Int): String {
if (n in 11..13) {
return "th"
}
when (n % 10) {
1 -> return "st"
2 -> return "nd"
3 -> return "rd"
else -> return "th"
}
}
establecer de esta manera
txt_chat_time_me.text = changeDateFormats("SERVER_DATE", "DATE")
Hay una manera más simple y segura de hacer esto. La función que necesitará usar es getDateFromDateString (dateString); Básicamente elimina el st / nd / rd / th de una cadena de fecha y simplemente lo analiza. Puede cambiar su SimpleDateFormat a cualquier cosa y esto funcionará.
public static final SimpleDateFormat sdf = new SimpleDateFormat("d");
public static final Pattern p = Pattern.compile("([0-9]+)(st|nd|rd|th)");
private static Date getDateFromDateString(String dateString) throws ParseException {
return sdf.parse(deleteOrdinal(dateString));
}
private static String deleteOrdinal(String dateString) {
Matcher m = p.matcher(dateString);
while (m.find()) {
dateString = dateString.replaceAll(Matcher.quoteReplacement(m.group(0)), m.group(1));
}
return dateString;
}
La pregunta es un poco vieja. Como esta pregunta es muy ruidosa, publicando lo que hice resuelto con el método estático como utilidad. ¡Solo copie, pegue y use!
public static String getFormattedDate(Date date){
Calendar cal=Calendar.getInstance();
cal.setTime(date);
//2nd of march 2015
int day=cal.get(Calendar.DATE);
if(!((day>10) && (day<19)))
switch (day % 10) {
case 1:
return new SimpleDateFormat("d''st'' ''of'' MMMM yyyy").format(date);
case 2:
return new SimpleDateFormat("d''nd'' ''of'' MMMM yyyy").format(date);
case 3:
return new SimpleDateFormat("d''rd'' ''of'' MMMM yyyy").format(date);
default:
return new SimpleDateFormat("d''th'' ''of'' MMMM yyyy").format(date);
}
return new SimpleDateFormat("d''th'' ''of'' MMMM yyyy").format(date);
}
Para probar purose
Ejemplo: llamarlo desde el método principal!
Date date = new Date();
Calendar cal=Calendar.getInstance();
cal.setTime(date);
for(int i=0;i<32;i++){
System.out.println(getFormattedDate(cal.getTime()));
cal.set(Calendar.DATE,(cal.getTime().getDate()+1));
}
Salida:
22nd of February 2018
23rd of February 2018
24th of February 2018
25th of February 2018
26th of February 2018
27th of February 2018
28th of February 2018
1st of March 2018
2nd of March 2018
3rd of March 2018
4th of March 2018
5th of March 2018
6th of March 2018
7th of March 2018
8th of March 2018
9th of March 2018
10th of March 2018
11th of March 2018
12th of March 2018
13th of March 2018
14th of March 2018
15th of March 2018
16th of March 2018
17th of March 2018
18th of March 2018
19th of March 2018
20th of March 2018
21st of March 2018
22nd of March 2018
23rd of March 2018
24th of March 2018
25th of March 2018
La siguiente es una respuesta más eficiente a la pregunta que un estilo de codificación difícil.
Para cambiar el día al número ordinal, necesita usar el siguiente suffix .
DD + TH = DDTH result >>>> 4TH
OR to spell the number add SP to the format
DD + SPTH = DDSPTH result >>> FOURTH
Encuentra mi respuesta completa en suffix pregunta.
Me gustaría contribuir con la respuesta moderna. La clase SimpleDateFormat
estaba bien para usar cuando se formuló la pregunta hace casi 8 años, pero debe evitarla ahora, ya que no solo está desactualizada hace tiempo, sino que también es notoriamente problemática. Use java.time
en java.time
lugar:
// ordinal indicators by numbers (1-based, cell 0 is wasted)
String[] ordinalIndicators = new String[31 + 1];
Arrays.fill(ordinalIndicators, 1, ordinalIndicators.length, "th");
ordinalIndicators[1] = ordinalIndicators[21] = ordinalIndicators[31] = "st";
ordinalIndicators[2] = ordinalIndicators[22] = "nd";
ordinalIndicators[3] = ordinalIndicators[23] = "rd";
DateTimeFormatter dayOfMonthFormatter = DateTimeFormatter.ofPattern("d");
LocalDate today = LocalDate.now(ZoneId.of("America/Menominee")).plusWeeks(1);
System.out.println(today.format(dayOfMonthFormatter)
+ ordinalIndicators[today.getDayOfMonth()]);
Ejecutando este fragmento justo ahora tengo
23 °
Una de las muchas características de java.time
es que es sencillo y confiable obtener el día del mes como int
, lo que obviamente es necesario para elegir el sufijo correcto de la tabla.
Te recomiendo que también escribas una prueba unitaria.
Enlace: tutorial de Oracle: Fecha y hora explicando cómo usar java.time
.
Muchos de los ejemplos aquí no funcionarán para 11, 12, 13. Esto es más genérico y funcionará para todos los casos.
switch (date) {
case 1:
case 21:
case 31:
return "" + date + "st";
case 2:
case 22:
return "" + date + "nd";
case 3:
case 23:
return "" + date + "rd";
default:
return "" + date + "th";
}
No hay nada en JDK para hacer esto.
static String[] suffixes =
// 0 1 2 3 4 5 6 7 8 9
{ "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th",
// 10 11 12 13 14 15 16 17 18 19
"th", "th", "th", "th", "th", "th", "th", "th", "th", "th",
// 20 21 22 23 24 25 26 27 28 29
"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th",
// 30 31
"th", "st" };
Date date = new Date();
SimpleDateFormat formatDayOfMonth = new SimpleDateFormat("d");
int day = Integer.parseInt(formatDateOfMonth.format(date));
String dayStr = day + suffixes[day];
O usando el calendario:
Calendar c = Calendar.getInstance();
c.setTime(date);
int day = c.get(Calendar.DAY_OF_MONTH);
String dayStr = day + suffixes[day];
Según los comentarios de @ thorbjørn-ravn-andersen, una tabla como esta puede ser útil al localizar:
static String[] suffixes =
{ "0th", "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th",
"10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th", "18th", "19th",
"20th", "21st", "22nd", "23rd", "24th", "25th", "26th", "27th", "28th", "29th",
"30th", "31st" };
No puedo estar satisfecho con las respuestas que requieren una solución solo en inglés basada en formatos manuales. He estado buscando una solución adecuada por un tiempo y finalmente la encontré.
Debería usar RuleBasedNumberFormat . Funciona perfectamente y es respetuoso de la configuración regional.
Si intentas ser consciente de i18n, la solución se complica aún más.
El problema es que en otros idiomas el sufijo puede depender no solo del número en sí mismo, sino también del sustantivo que cuenta. Por ejemplo, en ruso sería "2-ой день", pero "2-aя неделя" (estos significan "2 ° día", pero "2 ° semana"). Esto no se aplica si formateamos solo días, pero en un caso un poco más genérico debe ser consciente de la complejidad.
Creo que una buena solución (no tuve tiempo para implementarla realmente) sería extender SimpleDateFormetter para aplicar MessageFormat Local-aware antes de pasar a la clase padre. De esta forma, podría admitir, por ejemplo, los formatos de marzo% M para obtener "3-rd",% MM para obtener "03-rd" y% MMM para obtener "tercero". Desde fuera, esta clase se ve como SimpleDateFormatter normal, pero admite más formatos. Además, si este patrón fuera por error aplicado por SimpleDateFormetter regular, el resultado sería formateado incorrectamente, pero aún legible.
Si necesita esto en Android puede ver esta respuesta
Sin embargo, es una solución internacionalizada. Y no necesita reinventar la bicicleta;)
// https://github.com/google/guava
import static com.google.common.base.Preconditions.*;
String getDayOfMonthSuffix(final int n) {
checkArgument(n >= 1 && n <= 31, "illegal day of month: " + n);
if (n >= 11 && n <= 13) {
return "th";
}
switch (n % 10) {
case 1: return "st";
case 2: return "nd";
case 3: return "rd";
default: return "th";
}
}
La tabla de @kaliatech es agradable, pero dado que se repite la misma información, abre la posibilidad de un error. Tal error en realidad existe en la tabla para 7tn
, 17tn
y 27tn
(este error podría arreglarse a medida que pase el tiempo debido a la naturaleza fluida de , así que verifique el historial de versiones en la respuesta para ver el error).
String ordinal(int num)
{
String[] suffix = {"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"};
int m = num % 100;
return String.valueOf(num) + suffix[(m > 3 && m < 21) ? 0 : (m % 10)];
}
private String getCurrentDateInSpecificFormat(Calendar currentCalDate) {
String dayNumberSuffix = getDayNumberSuffix(currentCalDate.get(Calendar.DAY_OF_MONTH));
DateFormat dateFormat = new SimpleDateFormat(" d''" + dayNumberSuffix + "'' MMMM yyyy");
return dateFormat.format(currentCalDate.getTime());
}
private String getDayNumberSuffix(int day) {
if (day >= 11 && day <= 13) {
return "th";
}
switch (day % 10) {
case 1:
return "st";
case 2:
return "nd";
case 3:
return "rd";
default:
return "th";
}
}
public String getDaySuffix(int inDay)
{
String s = String.valueOf(inDay);
if (s.endsWith("1"))
{
return "st";
}
else if (s.endsWith("2"))
{
return "nd";
}
else if (s.endsWith("3"))
{
return "rd";
}
else
{
return "th";
}
}