dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.63k stars 4.57k forks source link

DateTime.ParseExact/ToString: inconsistent handling of abbreviated month names (MMM) in culture de-DE #68385

Closed jonathan-vogel-siemens closed 2 years ago

jonathan-vogel-siemens commented 2 years ago

Description

When trying to parse DateTime values from a string using (Try)ParseExact using culture de-DE, abbreviated month names are not parsed/formatted according to the culture's DateTimeFormat.AbbreviatedMonthNames (using format specifier MMM).

Reproduction Steps

Demo project can be found here: https://github.com/Jonathan-a35y/dotnet-datetime-bug

Expected behavior

DateTime.ToString and DateTime.Parse should adhere to a culture's DateTimeFormat.AbbreviatedMonthNames when parsing/formatting dates using the MMM format specifier

Actual behavior

DateTime.ToString and DateTime.Parse expect/add periods for some months, for others not.

Using culture de-DE with format 'd.MMM.yyyy'.
DateTimeFormat.AbbreviatedMonthNames: [Jan, Feb, Mär, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez]

  Parsing 1.Jan.2020
    FAILED!
    -> Formatted string differs: expected '1.Jan.2020', got '1.Jan..2020'
  Parsing 1.Feb.2020
    FAILED!
    -> Formatted string differs: expected '1.Feb.2020', got '1.Feb..2020'
  Parsing 1.Mär.2020
    OK: 01.03.2020
    -> Formatted string differs: expected '1.Mär.2020', got '1.März.2020'
  Parsing 1.Apr.2020
    FAILED!
    -> Formatted string differs: expected '1.Apr.2020', got '1.Apr..2020'
  Parsing 1.Mai.2020
    OK: 01.05.2020
  Parsing 1.Jun.2020
    OK: 01.06.2020
    -> Formatted string differs: expected '1.Jun.2020', got '1.Juni.2020'
  Parsing 1.Jul.2020
    OK: 01.07.2020
    -> Formatted string differs: expected '1.Jul.2020', got '1.Juli.2020'
  Parsing 1.Aug.2020
    FAILED!
    -> Formatted string differs: expected '1.Aug.2020', got '1.Aug..2020'
  Parsing 1.Sep.2020
    OK: 01.09.2020
    -> Formatted string differs: expected '1.Sep.2020', got '1.Sept..2020'
  Parsing 1.Okt.2020
    FAILED!
    -> Formatted string differs: expected '1.Okt.2020', got '1.Okt..2020'
  Parsing 1.Nov.2020
    FAILED!
    -> Formatted string differs: expected '1.Nov.2020', got '1.Nov..2020'
  Parsing 1.Dez.2020
    FAILED!
    -> Formatted string differs: expected '1.Dez.2020', got '1.Dez..2020'

Regression?

No response

Known Workarounds

No response

Configuration

Other information

No response

dotnet-issue-labeler[bot] commented 2 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-system-globalization See info in area-owners.md if you want to be subscribed.

Issue Details
### Description When trying to parse DateTime values from a string using (Try)ParseExact using culture de-DE, abbreviated month names are not parsed/formatted according to the culture's `DateTimeFormat.AbbreviatedMonthNames` (using format specifier MMM). ### Reproduction Steps Demo project can be found here: https://github.com/Jonathan-a35y/dotnet-datetime-bug ### Expected behavior DateTime.ToString and DateTime.Parse should adhere to a culture's `DateTimeFormat.AbbreviatedMonthNames` when parsing/formatting dates using the MMM format specifier ### Actual behavior DateTime.ToString and DateTime.Parse expect/add periods for some months, for others not. ``` Using culture de-DE with format 'd.MMM.yyyy'. DateTimeFormat.AbbreviatedMonthNames: [Jan, Feb, Mär, Apr, Mai, Jun, Jul, Aug, Sep, Okt, Nov, Dez] Parsing 1.Jan.2020 FAILED! -> Formatted string differs: expected '1.Jan.2020', got '1.Jan..2020' Parsing 1.Feb.2020 FAILED! -> Formatted string differs: expected '1.Feb.2020', got '1.Feb..2020' Parsing 1.Mär.2020 OK: 01.03.2020 -> Formatted string differs: expected '1.Mär.2020', got '1.März.2020' Parsing 1.Apr.2020 FAILED! -> Formatted string differs: expected '1.Apr.2020', got '1.Apr..2020' Parsing 1.Mai.2020 OK: 01.05.2020 Parsing 1.Jun.2020 OK: 01.06.2020 -> Formatted string differs: expected '1.Jun.2020', got '1.Juni.2020' Parsing 1.Jul.2020 OK: 01.07.2020 -> Formatted string differs: expected '1.Jul.2020', got '1.Juli.2020' Parsing 1.Aug.2020 FAILED! -> Formatted string differs: expected '1.Aug.2020', got '1.Aug..2020' Parsing 1.Sep.2020 OK: 01.09.2020 -> Formatted string differs: expected '1.Sep.2020', got '1.Sept..2020' Parsing 1.Okt.2020 FAILED! -> Formatted string differs: expected '1.Okt.2020', got '1.Okt..2020' Parsing 1.Nov.2020 FAILED! -> Formatted string differs: expected '1.Nov.2020', got '1.Nov..2020' Parsing 1.Dez.2020 FAILED! -> Formatted string differs: expected '1.Dez.2020', got '1.Dez..2020' ``` ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration - .NET SDK 6.0.202, Microsoft.NETCore.App 6.0.4 - Windows 10, v20H2 - Architecture: x64 ### Other information _No response_
Author: Jonathan-a35y
Assignees: -
Labels: `area-System.Globalization`, `untriaged`
Milestone: -
tarekgh commented 2 years ago

@Jonathan-a35y de-DE culture contains Genitive Month Names. if you call DateTimeFormat.AbbreviatedMonthGenitiveNames you will see the genitive month names. For de-DE the genitive month names are: [Jan., Feb., März, Apr., Mai, Juni, Juli, Aug., Sept., Okt., Nov., Dez., ]. This means when formatting a date containing the day as a number (i.e. using d or dd in the date pattern), then the genitive names will be used. As you are using the date pattern d.MMM.yyyy, this means the date will be formatted using the genitive month names. You will get a formatted date something like 1.Jan..2020. Note the genitive month name here is Jan. and not Jan. If you parse back the formatted string 1.Jan..2020 this will be parsed fine. You are not parsing the formatted string instead you are parsing your constructed string 1.Jan.2020 which is not a correct form. If you want to get the result you want with de-DE, you may use something like d.MMMyyyy or you format with day names instead of day number, like ddd.MMM.yyyy