python - lenguaje - Fecha de salida ordinal?
python tutorial (14)
Me pregunto si hay una manera rápida y fácil de dar salida a los ordinales dado un número en python.
Por ejemplo, dado el número 1
, me gustaría producir "1st"
, el número 2
, "2nd"
, etcétera, etcétera.
Esto es para trabajar con las fechas en un rastro de migas
Home > Venues > Bar Academy > 2009 > April > 01
es lo que se muestra actualmente
Me gustaría tener algo a lo largo de las líneas de
Home > Venues > Bar Academy > 2009 > April > 1st
Aquí está usando diccionarios como una función o como un lambda ...
Si miras los diccionarios al revés, puedes leerlos como ...
Todo termina en ''th''
... a menos que termine en 1, 2 o 3, termina en ''st'', ''nd'' o ''rd''
... a menos que termine en 11, 12 o 13, termina en ''th,'' th ''o'' th ''
# as a function
def ordinal(num):
return ''%d%s'' % (num, { 11: ''th'', 12: ''th'', 13: ''th'' }.get(num % 100, { 1: ''st'',2: ''nd'',3: ''rd'',}.get(num % 10, ''th'')))
# as a lambda
ordinal = lambda num : ''%d%s'' % (num, { 11: ''th'', 12: ''th'', 13: ''th'' }.get(num % 100, { 1: ''st'',2: ''nd'',3: ''rd'',}.get(num % 10, ''th'')))
Aquí hay una función que escribí como parte de un tipo de calendario de programa que escribí (no incluyo todo el programa). Agrega el ordinal correcto para cualquier número mayor que 0. Incluí un bucle para mostrar la salida.
def ordinals(num):
# st, nums ending in ''1'' except ''11''
if num[-1] == ''1'' and num[-2:] != ''11'':
return num + ''st''
# nd, nums ending in ''2'' except ''12''
elif num[-1] == ''2'' and num[-2:] != ''12'':
return num + ''nd''
# rd, nums ending in ''3'' except ''13''
elif num[-1] == ''3'' and num[-2:] != ''13'':
return num + ''rd''
# th, all other nums
else:
return num + ''th''
data = ''''
# print the first 366 ordinals (for leap year)
for i in range(1, 367):
data += ordinals(str(i)) + ''/n''
# print results to file
with open(''ordinals.txt'', ''w'') as wf:
wf.write(data)
Aquí hay una solución general aún más corta:
def foo(n):
return str(n) + {1: ''st'', 2: ''nd'', 3: ''rd''}.get(4 if 10 <= n % 100 < 20 else n % 10, "th")
Aunque las otras soluciones anteriores son probablemente más fáciles de entender a primera vista, esto funciona igual de bien mientras se usa un código de bit less.
Aquí hay una solución más general:
def ordinal(n):
if 10 <= n % 100 < 20:
return str(n) + ''th''
else:
return str(n) + {1 : ''st'', 2 : ''nd'', 3 : ''rd''}.get(n % 10, "th")
Corregido para entradas negativas, basado en el buen sol''n de eric.frederich (acaba de agregar abs
al usar %
):
def ordinal(num):
return ''%d%s'' % (num, { 11: ''th'', 12: ''th'', 13: ''th''}.get(abs(num) % 100, { 1: ''st'',2: ''nd'',3: ''rd'',}.get(abs(num) % 10, ''th'')))
Estos días usaría Arrow http://arrow.readthedocs.io/en/latest/ (que definitivamente no estaba disponible en ''09)
>>> import arrow
>>> from datetime import datetime
>>> arrow.get(datetime.utcnow()).format(''Do'')
''27th''
Excepto por el 1º, 2º y 3º, creo que todos solo añaden el ... 4º, 5º, 6º, 11º, 21º ... oh, oops ;-)
Creo que esto podría funcionar:
def ordinal(num):
ldig = num % 10
l2dig = (num // 10) % 10
if l2dig == 1:
suffix = ''th''
elif ldig == 1:
suffix = ''st''
elif ldig == 2:
suffix = ''nd''
elif ldig == 3:
suffix = ''rd''
else:
suffix = ''th''
return ''%d%s'' % (num, suffix)
Hice una función que parece funcionar en este caso. Simplemente pase un objeto de fecha, y usará el día para descubrir el sufijo. Espero eso ayude
from datetime import date
def get_day_ordinal(d):
sDay = ''%dth''
if d.day <= 10 or d.day >= 21:
sDay = ''%dst'' if d.day % 10 == 1 else sDay
sDay = ''%dnd'' if d.day % 10 == 2 else sDay
sDay = ''%drd'' if d.day % 10 == 3 else sDay
return sDay % d.day
d = date.today()
print get_day_ordinal(d)
No estoy seguro de si existía hace 5 años cuando hizo esta pregunta, pero el paquete de inflect tiene una función para hacer lo que está buscando:
>>> import inflect
>>> p = inflect.engine()
>>> for i in range(1,32):
... print p.ordinal(i)
...
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
O acorte la respuesta de David con:
if 4 <= day <= 20 or 24 <= day <= 30:
suffix = "th"
else:
suffix = ["st", "nd", "rd"][day % 10 - 1]
Quería usar ordinales para un proyecto mío y después de algunos prototipos creo que este método, aunque no pequeño, funcionará para cualquier número entero positivo, sí cualquier número entero.
Funciona al determinar si el número está por encima o por debajo de 20, si el número está por debajo de 20, convertirá el int 1 en la cadena 1ra, 2a, 2da; 3, 3ra; y al resto se le agregará "st".
Para números mayores de 20, tomará el último y el segundo hasta el último dígito, al que he llamado decenas y unidades, respectivamente, y los probaré para ver qué agregar al número.
Esto está en python por cierto, así que no estoy seguro de si otros idiomas podrán encontrar el último o el segundo hasta el último dígito en una cadena, si lo hacen debería traducirse con bastante facilidad.
def o(numb):
if numb < 20: #determining suffix for < 20
if numb == 1:
suffix = ''st''
elif numb == 2:
suffix = ''nd''
elif numb == 3:
suffix = ''rd''
else:
suffix = ''th''
else: #determining suffix for > 20
tens = str(numb)
tens = tens[-2]
unit = str(numb)
unit = unit[-1]
if tens == "1":
suffix = "th"
else:
if unit == "1":
suffix = ''st''
elif unit == "2":
suffix = ''nd''
elif unit == "3":
suffix = ''rd''
else:
suffix = ''th''
return str(numb)+ suffix
Llamé a la función "o" para facilitar el uso y puedo invocarlo importando el nombre del archivo que llamé "ordinal" por ordinal de importación y luego ordinal.o (número).
Déjame saber lo que piensas: D
PD. He publicado esta respuesta en otra pregunta de ordinales pero me di cuenta de que esta es más aplicable considerando que es python.
Tuve que convertir un script de javascript donde tenía un fn útil que reproducía el obj de fecha de phps. Muy similar
def ord(n):
return str(n)+("th" if 4<=n%100<=20 else {1:"st",2:"nd",3:"rd"}.get(n%10, "th"))
esto atado con mi fechador:
def dtStylish(dt,f):
return dt.strftime(f).replace("{th}", ord(dt.day))
ps -I get aquí de otro hilo que se informó como un duplicado pero no fue del todo ya que ese hilo también se dirigió al tema de la fecha
Una solución más general y más corta (como una función):
def get_ordinal(num)
ldig = num % 10
l2dig = (num // 10) % 10
if (l2dig == 1) or (ldig > 3):
return ''%d%s'' % (num, ''th'')
else:
return ''%d%s'' % (num, {1: ''st'', 2: ''nd'', 3: ''rd''}.get(ldig))
Solo combiné las soluciones y bibliotecas de David (como lo hicieron los deereedubs). Incluso puede reemplazar las variables (ldig, l2dig) por las matemáticas reales (ya que l2dig se usa solo una vez), luego obtiene cuatro líneas de código.
def ordinal(n):
return ["th", "st", "nd", "rd"][n%10 if n%10<4 and not (10<n%100<14) else 0]