问题
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 be4
, right aligned (>
) for numbers and strings and filled with0
s (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