【问题标题】:How to change Date String Format (20th Oct 2052 -> 2052-10-20)如何更改日期字符串格式(2052 年 10 月 20 日 -> 2052-10-20)
【发布时间】:2019-06-15 23:25:54
【问题描述】:

块引用

我有一个格式为日月年的日期字符串,例如 1984 年 3 月 1 日、1973 年 4 月 4 日、2006 年 5 月 22 日,其中:

日期在集合 {"1st","2nd","3rd",...,'"30th","31st"}

月份在集合中 {"Jan","Feb","Mar",...,"Dec"}

年份在 [1900,2100] 范围内

我必须将日期字符串转换为 YYYY-MM-DD 格式,例如: 1984 年 3 月 1 日 -> 1984-03-01 1973 年 4 月 4 日 -> 1973-04-04

(函数reformatDate有以下参数: dates[dates[0],...,dates[n-1]] 是日期字符串数组,格式为 Day Month Year)

示例输入 4 2052 年 10 月 20 日 1933 年 6 月 6 日 1960 年 5 月 26 日 1958 年 9 月 20 日

样本输出 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

【问题讨论】:

  • 您可以使用外部模块吗? datetime 有函数 strptime 可以做到这一点。
  • 如果可能,我宁愿不使用外部模块
  • @RogerPereira 查看我写的解决方案,它不使用任何外部模块

标签: python date


【解决方案1】:

这是使用datetime 模块的一种方法。

例如:

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"))

输出:

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

注意:re.sub(r"(st|th|rd)", "", i) 从日期中删除 st、th、rd。

【讨论】:

    【解决方案2】:

    这是一种专门针对您的案例的临时解决方案。您可以通过将自己的月份名称传递给数字映射来避免使用日历包。不过,可能还有更通用和 Pythonic 的解决方案。

    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
    

    【讨论】:

    • 运行正常,但不适用于我的示例输入。我的输入是一个 txt 文件,其中第一行是日期数,下一行是日期本身,我必须更改格式。有点像:4 1973 年 7 月 3 日 2013 年 9 月 24 日 2075 年 5 月 22 日 1956 年 2 月 27 日
    【解决方案3】:

    您可以将lambda 与列表理解一起使用:

    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]
    

    输出:

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

    【讨论】:

      【解决方案4】:

      由于所有先前的答案都使用输出模块(redatetimecalendar 在标准 Python 库中,但它们仍然需要按原样导入),我用内置 python 编写了一个解决方案职能。不要犹豫,提出改进建议:

      #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]
      

      输出:

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

      【讨论】:

      • 我需要这个条目是通用的。我不能让数组 d 带有条目。该条目必须是一个文件,其中包含我要更改的日期数,然后是日期本身
      • 这个列表是一个例子。你的文件是如何格式化的?我可以相应地更新我的答案
      • 文件的第一行包含要更改的日期数,下一行包含日期。
      • 我必须完成代码中的函数reformatDate(dates)。您的解决方案确实有效,但这不是我需要的方式。感谢您的帮助。
      【解决方案5】:

      你写的:

      如果可能,我宁愿不使用外部模块

      在评论中,但 datetimecalendar 是标准库的一部分,不是外部模块!也就是说:这些模块是 Python 语言的一部分,就像整数、循环、函数和类一样。 (嗯......几乎:见Is the Python standard library really standard?Which parts of the python standard library are guaranteed to be available?。)。记住这一点:

      Python 有“包含电池”的理念。 (Guido van Rossumhttps://docs.python.org/3/tutorial/stdlib.html#batteries-included

      您不应试图避免使用标准库,而应学习如何使用它。

      如果您还想自己尝试这样做,可以使用通常的单线:

      >>> 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']
      

      解释:

      • {:0>4} 格式表示:宽度为4,数字和字符串右对齐(@9​​87654331@),填充0s(参见:https://docs.python.org/3.7/library/string.html#formatspec)。
      • month_names.index(m)+1 是月份的数字(如果月份未知,则失败)
      • d.rstrip("stnrdh") 只是清除天数的后缀(“st”、“nd”、“rd”、“th”)
      • map(str.split, date_strings) 将日期分成三部分(日、月、年)。

      请注意,如果输入无效,此代码将失败。换句话说,除非输入经过验证,否则我不会依赖此代码。

      【讨论】:

      • 有趣简洁的解决方案
      • 我需要 date_strings 数组是通用的。我不能有具体的日期。它应该适用于所有日期
      • @RogerPereira 如果日期格式正确,这应该适用于所有日期。 “通用”是什么意思?
      • 输入是一个文件,其中第一行我有要更改的日期数,下一行包含将要更改的日期。当我说通用时,我的意思是它必须适用于所有日期,而不仅仅是您放在数组 date_strings 上的日期
      • @RogerPereira 它应该适用于所有日期。从文件中读取行是另一个问题:例如参见stackoverflow.com/questions/3277503/…
      猜你喜欢
      • 1970-01-01
      • 2012-08-17
      • 1970-01-01
      • 1970-01-01
      • 2013-10-25
      • 1970-01-01
      • 2014-12-19
      • 1970-01-01
      • 2020-03-07
      相关资源
      最近更新 更多