How to change Date String Format (20th Oct 2052 -> 2052-10-20)

孤者浪人 提交于 2021-01-29 16:15:56

问题


Blockquote

I have a date string in the format Day Month Year, like 1st Mar 1984, 4th Apr 1973, 22nd May 2006, where:

Day is in the set {"1st","2nd","3rd",...,'"30th","31st"}

Month is in the set {"Jan","Feb","Mar",...,"Dec"}

Year is in the range [1900,2100]

I gotta convert the date string to the format YYYY-MM-DD, like: 1st Mar 1984 -> 1984-03-01 4th Apr 1973 -> 1973-04-04

(The function reformatDate has the following parameters: dates[dates[0],...,dates[n-1]] is an array of date strings in the format Day Month Year)

Sample Input 4 20th Oct 2052 6th Jun 1933 26th May 1960 20th Sep 1958

Sample Output 2052-10-20 1933-06-06 1960-05-26 1958-09-20

enter code here
    def reformatDate(dates):
    # write your code here
    if __name__ == '__main__':
        fptr = open(os.environ['OUTPUT_PATH'], 'w')
        dates_count = int(input().strip())
        dates = []
        for _ in range(dates_count):
            dates.item = input()
            dates.append(dates_item)       
        result = reformatDate(dates)
        fptr.write('\n'.join(result))
        fptr.write('\n')
        fptr.close

回答1:


This is one approach using datetime module.

Ex:

import datetime
import re    

lst = ["20th Oct 2052", "6th Jun 1933", "26th May 1960", "20th Sep 1958"]
for i in lst:
    print(datetime.datetime.strptime(re.sub(r"(st|th|rd)", "", i), "%d %b %Y").strftime("%Y-%m-%d"))

Output:

2052-10-20
1933-06-06
1960-05-26
1958-09-20

Note: re.sub(r"(st|th|rd)", "", i) to remove st, th, rd from date.




回答2:


This is kind of an ad-hoc solution specific for your case. You could avoid the use of calendar package by passing your own month name to number mapping. There are probably more generic and pythonic solutions though.

import calendar 

def reformatDate(dates):
    output_dates = []
    for date in output_dates:
        fields = date.split()
        day = fields[0][:-2]
        month = str(list(calendar.month_abbr).index(fields[1]))
        year = fields[2]
        output_date = year + "-" + month + "-" + day
        output_dates.append(output_date)
    return output_dates



回答3:


You can use a lambda with a list comprehension:

import re
lst = ["20th Oct 2052", "6th Jun 1933", "26th May 1960", "20th Sep 1958"]
m = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
new_data = [(lambda x:f'{x[-1]}-{m.index(x[1])+1}-{x[0]}')(re.findall('\d+|\w{3,}', c)) for c in lst]

Output:

['2052-10-20', '1933-6-6', '1960-5-26', '1958-9-20']



回答4:


As all the previous answers use output modules (re, datetime or calendar are in the standard Python library but still, they require to be imported as such), I wrote a solution with built-in python functions. Don't hesitate to suggest improvements:

#your input
d = ["20th Oct 2052", "6th Jun 1933", "26th May 1960", "20th Sep 1958"]
#first split the data
ds=[l.strip().split(" ") for l in d]
#then create a dictionary for month
month_dict={'Jan':'01', 'Feb':'02', 'Mar':'03', 'Apr':'04', 'May':'05', 'Jun':'06', 'Jul':'07', 'Aug':'08', 'Sep':'09', 'Oct':'10', 'Nov':'11', 'Dec':'12'}

#function to filter digits from a string.
#a strong advantage of filtering digits is that it doesn't matter whether or not days are written with st, nd or rd
def digit_from_string(x):
    s = ''.join(filter(str.isdigit, x))
    #in case only one digit was extracted (e.g., 2), add a 0 in front (e.g., 02)
    if len(s) == 1:
        s='0'+s
    return s

#iterates on the splitted data; v[0] corresponds to the day, v[1] the month and v[2] the year
ds=[{'day': digit_from_string(v[0]),
    'month': digit_from_string(month_dict[v[1]]),
    'year': digit_from_string(v[2])}
   for v in ds]

#format the output
output=['{0}-{1}-{2}'.format(x['year'],x['month'],x['day']) for x in ds]

Output:

['2052-10-20', '1933-06-06', '1960-05-26', '1958-09-20']



回答5:


You wrote:

I'd rather not use outside modules if possible

in a comment, but datetime and calendar are parts of the standard library and are not external modules! That is: these modules are part of the Python language as integers, loops, functions and classes are. (Well... almost: see Is the Python standard library really standard? and Which parts of the python standard library are guaranteed to be available?.). Remember this:

Python has a “batteries included” philosophy. (Guido van Rossum, https://docs.python.org/3/tutorial/stdlib.html#batteries-included)

You should not try to avoid to use the standard library but rather learn how to use it.

If you want still want to try do this on your own, you can play with the usual one-liner:

>>> date_strings = ["20th Oct 2052", "6th Jun 1933", "26th May 1960", "20th Sep 1958"]
>>> month_names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
>>> ["{:0>4}-{:0>2}-{:0>2}".format(y, month_names.index(m)+1, d.rstrip("stnrdh")) for d,m,y in map(str.split, date_strings)]
['2052-10-20', '1933-06-06', '1960-05-26', '1958-09-20']

Explanation:

  • The format {:0>4} means: the width shall be 4, right aligned (>) for numbers and strings and filled with 0s (see: https://docs.python.org/3.7/library/string.html#formatspec).
  • month_names.index(m)+1 is the numer of the month (fails if the month is unknown)
  • d.rstrip("stnrdh") just clears the suffix of the day number ("st", "nd", "rd", "th")
  • map(str.split, date_strings) splits the dates into three parts (day, month, year).

Please note that this code will fail if the input is not valid. In other words, I wouldn't rely on this code unless input is validated.



来源:https://stackoverflow.com/questions/54309166/how-to-change-date-string-format-20th-oct-2052-2052-10-20

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!