0

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
Roger Pereira
  • 69
  • 2
  • 5

5 Answers5

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.

Rakesh
  • 81,458
  • 17
  • 76
  • 113
0

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
MattSt
  • 1,024
  • 2
  • 16
  • 35
  • It ran ok but did not work for the sample input I have. My input is a txt file where I have on the first line the number of dates and the next lines with the dates themselves I gotta change the format. It's something llike: 4 3rd Jul 1973 24th Sep 2013 22nd May 2075 27th Feb 1956 – Roger Pereira Jan 23 '19 at 18:20
0

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']
Ajax1234
  • 69,937
  • 8
  • 61
  • 102
0

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']
florian
  • 881
  • 2
  • 8
  • 24
  • I need the entry to be generic. I can't have the array d with the entries. The entry must be a file with the number of dates I wanna change and then the dates themselves – Roger Pereira Jan 23 '19 at 18:15
  • The list was an example. How is your file formatted ? I can update my answer accordingly – florian Jan 24 '19 at 09:35
  • The file has in the first line the number of the dates to be changed and the next lines contain the dates. – Roger Pereira Jan 24 '19 at 11:33
  • i gotta complete the function reformatDate(dates) as it's in the code. Your solution actually works but it's not the way I need it. Thanks for your help. – Roger Pereira Jan 24 '19 at 17:59
0

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.

jferard
  • 7,835
  • 2
  • 22
  • 35
  • interesting and concise solution – florian Jan 23 '19 at 09:09
  • I need that the date_strings array be generic. I can`t have specific dates. It should work with all dates – Roger Pereira Jan 23 '19 at 18:17
  • @RogerPereira This should work for all dates if they are well formed. What do you mean by "generic"? – jferard Jan 23 '19 at 19:06
  • The input is a file where in the first line I have the number of dates to be changed and the next lines contain the dates that will be changed. When I say generic I meant it must work with all dates, not only the ones you put on the array date_strings – Roger Pereira Jan 24 '19 at 11:36
  • @RogerPereira It should work with all dates. To read lines from a file is another question : see https://stackoverflow.com/questions/3277503/how-to-read-a-file-line-by-line-into-a-list for example. – jferard Jan 24 '19 at 21:14