Parsing leap year day without year always fails in C#












-1














I'm trying to parse birthdays in the format of d/M without any year specified.



Using DateTime.TryParseExact(birthday, "d/M", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate) works most of the time, except when the birthday is at leap year day (aka 29/2), and the parsing never succeeds because it is default to current year. Using DatTimeStyles.NoCurrentDateDefault does not work either since it defaults to year = 1, which is not a leap year.



How do I do the parsing so it does not involve a hack (I don't want to parse it manually or manually add an arbitrary year to parse it as a full date either, they are all ugly and potentially fragile) and still work across all possible dates, including leap day? Existing questions does not help at all since nobody bothers to check if they work for leap day at all. I tried all of them and none of them worked.










share|improve this question





























    -1














    I'm trying to parse birthdays in the format of d/M without any year specified.



    Using DateTime.TryParseExact(birthday, "d/M", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate) works most of the time, except when the birthday is at leap year day (aka 29/2), and the parsing never succeeds because it is default to current year. Using DatTimeStyles.NoCurrentDateDefault does not work either since it defaults to year = 1, which is not a leap year.



    How do I do the parsing so it does not involve a hack (I don't want to parse it manually or manually add an arbitrary year to parse it as a full date either, they are all ugly and potentially fragile) and still work across all possible dates, including leap day? Existing questions does not help at all since nobody bothers to check if they work for leap day at all. I tried all of them and none of them worked.










    share|improve this question



























      -1












      -1








      -1


      1





      I'm trying to parse birthdays in the format of d/M without any year specified.



      Using DateTime.TryParseExact(birthday, "d/M", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate) works most of the time, except when the birthday is at leap year day (aka 29/2), and the parsing never succeeds because it is default to current year. Using DatTimeStyles.NoCurrentDateDefault does not work either since it defaults to year = 1, which is not a leap year.



      How do I do the parsing so it does not involve a hack (I don't want to parse it manually or manually add an arbitrary year to parse it as a full date either, they are all ugly and potentially fragile) and still work across all possible dates, including leap day? Existing questions does not help at all since nobody bothers to check if they work for leap day at all. I tried all of them and none of them worked.










      share|improve this question















      I'm trying to parse birthdays in the format of d/M without any year specified.



      Using DateTime.TryParseExact(birthday, "d/M", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate) works most of the time, except when the birthday is at leap year day (aka 29/2), and the parsing never succeeds because it is default to current year. Using DatTimeStyles.NoCurrentDateDefault does not work either since it defaults to year = 1, which is not a leap year.



      How do I do the parsing so it does not involve a hack (I don't want to parse it manually or manually add an arbitrary year to parse it as a full date either, they are all ugly and potentially fragile) and still work across all possible dates, including leap day? Existing questions does not help at all since nobody bothers to check if they work for leap day at all. I tried all of them and none of them worked.







      c# datetime






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 21 at 1:28

























      asked Nov 20 at 4:08









      user2988819

      183




      183
























          2 Answers
          2






          active

          oldest

          votes


















          2














          A day and a month does not make a date - therefore they can't be parsed as a DateTime value without assuming a year. The .NET Framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption.



          The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate - It stores a day and a month but no year.



          However, it doesn't have Parse or TryParse methods - so for that you still need to manually manipulate the input string and add a year (that is a leap year like 2016) in order to use the DateTime's TryParseExact method.



          Update



          As Matt Johnson wrote in his comment, Noda Time does provide a way for parsing text as an AnnualDate, using the AnnualDatePattern class.

          The documentation has a page called Patterns for AnnualDate values that lists the supported patterns.






          share|improve this answer























          • Nicely worded and upvoted
            – TheGeneral
            Nov 20 at 9:39










          • Noda Time does have parsing for AnnualDate. It's handled by the AnnualDatePattern class. See Text Handling and Patterns for AnnualDate values in the user guide.
            – Matt Johnson
            Nov 20 at 17:09










          • @MattJohnson Thanks for the comment and links. I've edited them into my answer.
            – Zohar Peled
            Nov 20 at 19:17



















          2














          This question lacks the appropriate details, however



          If you just want to parse a birth date and month including leap year dates, then just added a leap year to the end of the date.



          I am not sure what you expect to do here, however you could try this



          birthday = $"{birthday}/2016"; // leap year

          DateTime.TryParseExact(birthday, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate);


          Update




          my question is how to not make TryParseExact assume the year
          automatically by manually overriding it in some way




          To be technical here, no you have to specify the leap year in the string if you are parsing a leap year month and day exclusively as in your example



          There is a lot of checks and balances the TryParseExact method does, however here are the important bits.



          In short, it uses the current year or year 1, and there is no way to tell it to choose a leap year specifically



          private static bool CheckDefaultDateTime(ref DateTimeResult result, ref Calendar cal, DateTimeStyles styles)
          {
          if ((result.flags & ParseFlags.CaptureOffset) != (ParseFlags) 0 && (result.Month != -1 || result.Day != -1) && ((result.Year == -1 || (result.flags & ParseFlags.YearDefault) != (ParseFlags) 0) && (result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags) 0))
          {
          result.SetFailure(ParseFailureKind.Format, "Format_MissingIncompleteDate", (object) null);
          return false;
          }
          if (result.Year == -1 || result.Month == -1 || result.Day == -1)
          {
          DateTime dateTimeNow = DateTimeParse.GetDateTimeNow(ref result, ref styles);
          if (result.Month == -1 && result.Day == -1)
          {
          if (result.Year == -1)
          {
          if ((styles & DateTimeStyles.NoCurrentDateDefault) != DateTimeStyles.None)
          {
          cal = GregorianCalendar.GetDefaultInstance();
          result.Year = result.Month = result.Day = 1;
          }
          else
          {
          result.Year = cal.GetYear(dateTimeNow);
          result.Month = cal.GetMonth(dateTimeNow);
          result.Day = cal.GetDayOfMonth(dateTimeNow);
          }
          }
          else
          {
          result.Month = 1;
          result.Day = 1;
          }
          }
          else
          {
          if (result.Year == -1)
          result.Year = cal.GetYear(dateTimeNow);
          if (result.Month == -1)
          result.Month = 1;
          if (result.Day == -1)
          result.Day = 1;
          }
          }
          if (result.Hour == -1)
          result.Hour = 0;
          if (result.Minute == -1)
          result.Minute = 0;
          if (result.Second == -1)
          result.Second = 0;
          if (result.era == -1)
          result.era = 0;
          return true;
          }





          share|improve this answer























          • Yes, I am aware it could be done like this. However string mangling is fragile, and if it's used this way it completely nullifies the point of using DateTime.ParseExact (that is, to not mangle strings yourself), which means I'd be better just parse the components myself.
            – user2988819
            Nov 20 at 4:35










          • @user2988819 sure you could parse it your self, and create a datetime out of it, however in the end you are going to have to make the year a leap year for those special cases
            – TheGeneral
            Nov 20 at 4:38










          • @TheGeneral I'm currently storing the birthday with a dummy leap year anyway. However there are no ways to supply a default year when doing DateTime.ParseExact, which is really a bummer, especially when there is already a DateTimeStyles that sets the default year to something other than the current year.
            – user2988819
            Nov 20 at 4:41






          • 2




            @user2988819 would you believe me if i said you cant?
            – TheGeneral
            Nov 20 at 4:52






          • 3




            Your question does not make sense, that's why you've got so many downvotes and repeated comments. A day and a month does not make a date - therefor they can't be parsed as a DateTime value without assuming a year. The .Net framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption. The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate.
            – Zohar Peled
            Nov 20 at 7:23











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53386081%2fparsing-leap-year-day-without-year-always-fails-in-c-sharp%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          A day and a month does not make a date - therefore they can't be parsed as a DateTime value without assuming a year. The .NET Framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption.



          The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate - It stores a day and a month but no year.



          However, it doesn't have Parse or TryParse methods - so for that you still need to manually manipulate the input string and add a year (that is a leap year like 2016) in order to use the DateTime's TryParseExact method.



          Update



          As Matt Johnson wrote in his comment, Noda Time does provide a way for parsing text as an AnnualDate, using the AnnualDatePattern class.

          The documentation has a page called Patterns for AnnualDate values that lists the supported patterns.






          share|improve this answer























          • Nicely worded and upvoted
            – TheGeneral
            Nov 20 at 9:39










          • Noda Time does have parsing for AnnualDate. It's handled by the AnnualDatePattern class. See Text Handling and Patterns for AnnualDate values in the user guide.
            – Matt Johnson
            Nov 20 at 17:09










          • @MattJohnson Thanks for the comment and links. I've edited them into my answer.
            – Zohar Peled
            Nov 20 at 19:17
















          2














          A day and a month does not make a date - therefore they can't be parsed as a DateTime value without assuming a year. The .NET Framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption.



          The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate - It stores a day and a month but no year.



          However, it doesn't have Parse or TryParse methods - so for that you still need to manually manipulate the input string and add a year (that is a leap year like 2016) in order to use the DateTime's TryParseExact method.



          Update



          As Matt Johnson wrote in his comment, Noda Time does provide a way for parsing text as an AnnualDate, using the AnnualDatePattern class.

          The documentation has a page called Patterns for AnnualDate values that lists the supported patterns.






          share|improve this answer























          • Nicely worded and upvoted
            – TheGeneral
            Nov 20 at 9:39










          • Noda Time does have parsing for AnnualDate. It's handled by the AnnualDatePattern class. See Text Handling and Patterns for AnnualDate values in the user guide.
            – Matt Johnson
            Nov 20 at 17:09










          • @MattJohnson Thanks for the comment and links. I've edited them into my answer.
            – Zohar Peled
            Nov 20 at 19:17














          2












          2








          2






          A day and a month does not make a date - therefore they can't be parsed as a DateTime value without assuming a year. The .NET Framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption.



          The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate - It stores a day and a month but no year.



          However, it doesn't have Parse or TryParse methods - so for that you still need to manually manipulate the input string and add a year (that is a leap year like 2016) in order to use the DateTime's TryParseExact method.



          Update



          As Matt Johnson wrote in his comment, Noda Time does provide a way for parsing text as an AnnualDate, using the AnnualDatePattern class.

          The documentation has a page called Patterns for AnnualDate values that lists the supported patterns.






          share|improve this answer














          A day and a month does not make a date - therefore they can't be parsed as a DateTime value without assuming a year. The .NET Framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption.



          The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate - It stores a day and a month but no year.



          However, it doesn't have Parse or TryParse methods - so for that you still need to manually manipulate the input string and add a year (that is a leap year like 2016) in order to use the DateTime's TryParseExact method.



          Update



          As Matt Johnson wrote in his comment, Noda Time does provide a way for parsing text as an AnnualDate, using the AnnualDatePattern class.

          The documentation has a page called Patterns for AnnualDate values that lists the supported patterns.







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 20 at 19:16

























          answered Nov 20 at 9:13









          Zohar Peled

          52.4k73273




          52.4k73273












          • Nicely worded and upvoted
            – TheGeneral
            Nov 20 at 9:39










          • Noda Time does have parsing for AnnualDate. It's handled by the AnnualDatePattern class. See Text Handling and Patterns for AnnualDate values in the user guide.
            – Matt Johnson
            Nov 20 at 17:09










          • @MattJohnson Thanks for the comment and links. I've edited them into my answer.
            – Zohar Peled
            Nov 20 at 19:17


















          • Nicely worded and upvoted
            – TheGeneral
            Nov 20 at 9:39










          • Noda Time does have parsing for AnnualDate. It's handled by the AnnualDatePattern class. See Text Handling and Patterns for AnnualDate values in the user guide.
            – Matt Johnson
            Nov 20 at 17:09










          • @MattJohnson Thanks for the comment and links. I've edited them into my answer.
            – Zohar Peled
            Nov 20 at 19:17
















          Nicely worded and upvoted
          – TheGeneral
          Nov 20 at 9:39




          Nicely worded and upvoted
          – TheGeneral
          Nov 20 at 9:39












          Noda Time does have parsing for AnnualDate. It's handled by the AnnualDatePattern class. See Text Handling and Patterns for AnnualDate values in the user guide.
          – Matt Johnson
          Nov 20 at 17:09




          Noda Time does have parsing for AnnualDate. It's handled by the AnnualDatePattern class. See Text Handling and Patterns for AnnualDate values in the user guide.
          – Matt Johnson
          Nov 20 at 17:09












          @MattJohnson Thanks for the comment and links. I've edited them into my answer.
          – Zohar Peled
          Nov 20 at 19:17




          @MattJohnson Thanks for the comment and links. I've edited them into my answer.
          – Zohar Peled
          Nov 20 at 19:17













          2














          This question lacks the appropriate details, however



          If you just want to parse a birth date and month including leap year dates, then just added a leap year to the end of the date.



          I am not sure what you expect to do here, however you could try this



          birthday = $"{birthday}/2016"; // leap year

          DateTime.TryParseExact(birthday, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate);


          Update




          my question is how to not make TryParseExact assume the year
          automatically by manually overriding it in some way




          To be technical here, no you have to specify the leap year in the string if you are parsing a leap year month and day exclusively as in your example



          There is a lot of checks and balances the TryParseExact method does, however here are the important bits.



          In short, it uses the current year or year 1, and there is no way to tell it to choose a leap year specifically



          private static bool CheckDefaultDateTime(ref DateTimeResult result, ref Calendar cal, DateTimeStyles styles)
          {
          if ((result.flags & ParseFlags.CaptureOffset) != (ParseFlags) 0 && (result.Month != -1 || result.Day != -1) && ((result.Year == -1 || (result.flags & ParseFlags.YearDefault) != (ParseFlags) 0) && (result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags) 0))
          {
          result.SetFailure(ParseFailureKind.Format, "Format_MissingIncompleteDate", (object) null);
          return false;
          }
          if (result.Year == -1 || result.Month == -1 || result.Day == -1)
          {
          DateTime dateTimeNow = DateTimeParse.GetDateTimeNow(ref result, ref styles);
          if (result.Month == -1 && result.Day == -1)
          {
          if (result.Year == -1)
          {
          if ((styles & DateTimeStyles.NoCurrentDateDefault) != DateTimeStyles.None)
          {
          cal = GregorianCalendar.GetDefaultInstance();
          result.Year = result.Month = result.Day = 1;
          }
          else
          {
          result.Year = cal.GetYear(dateTimeNow);
          result.Month = cal.GetMonth(dateTimeNow);
          result.Day = cal.GetDayOfMonth(dateTimeNow);
          }
          }
          else
          {
          result.Month = 1;
          result.Day = 1;
          }
          }
          else
          {
          if (result.Year == -1)
          result.Year = cal.GetYear(dateTimeNow);
          if (result.Month == -1)
          result.Month = 1;
          if (result.Day == -1)
          result.Day = 1;
          }
          }
          if (result.Hour == -1)
          result.Hour = 0;
          if (result.Minute == -1)
          result.Minute = 0;
          if (result.Second == -1)
          result.Second = 0;
          if (result.era == -1)
          result.era = 0;
          return true;
          }





          share|improve this answer























          • Yes, I am aware it could be done like this. However string mangling is fragile, and if it's used this way it completely nullifies the point of using DateTime.ParseExact (that is, to not mangle strings yourself), which means I'd be better just parse the components myself.
            – user2988819
            Nov 20 at 4:35










          • @user2988819 sure you could parse it your self, and create a datetime out of it, however in the end you are going to have to make the year a leap year for those special cases
            – TheGeneral
            Nov 20 at 4:38










          • @TheGeneral I'm currently storing the birthday with a dummy leap year anyway. However there are no ways to supply a default year when doing DateTime.ParseExact, which is really a bummer, especially when there is already a DateTimeStyles that sets the default year to something other than the current year.
            – user2988819
            Nov 20 at 4:41






          • 2




            @user2988819 would you believe me if i said you cant?
            – TheGeneral
            Nov 20 at 4:52






          • 3




            Your question does not make sense, that's why you've got so many downvotes and repeated comments. A day and a month does not make a date - therefor they can't be parsed as a DateTime value without assuming a year. The .Net framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption. The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate.
            – Zohar Peled
            Nov 20 at 7:23
















          2














          This question lacks the appropriate details, however



          If you just want to parse a birth date and month including leap year dates, then just added a leap year to the end of the date.



          I am not sure what you expect to do here, however you could try this



          birthday = $"{birthday}/2016"; // leap year

          DateTime.TryParseExact(birthday, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate);


          Update




          my question is how to not make TryParseExact assume the year
          automatically by manually overriding it in some way




          To be technical here, no you have to specify the leap year in the string if you are parsing a leap year month and day exclusively as in your example



          There is a lot of checks and balances the TryParseExact method does, however here are the important bits.



          In short, it uses the current year or year 1, and there is no way to tell it to choose a leap year specifically



          private static bool CheckDefaultDateTime(ref DateTimeResult result, ref Calendar cal, DateTimeStyles styles)
          {
          if ((result.flags & ParseFlags.CaptureOffset) != (ParseFlags) 0 && (result.Month != -1 || result.Day != -1) && ((result.Year == -1 || (result.flags & ParseFlags.YearDefault) != (ParseFlags) 0) && (result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags) 0))
          {
          result.SetFailure(ParseFailureKind.Format, "Format_MissingIncompleteDate", (object) null);
          return false;
          }
          if (result.Year == -1 || result.Month == -1 || result.Day == -1)
          {
          DateTime dateTimeNow = DateTimeParse.GetDateTimeNow(ref result, ref styles);
          if (result.Month == -1 && result.Day == -1)
          {
          if (result.Year == -1)
          {
          if ((styles & DateTimeStyles.NoCurrentDateDefault) != DateTimeStyles.None)
          {
          cal = GregorianCalendar.GetDefaultInstance();
          result.Year = result.Month = result.Day = 1;
          }
          else
          {
          result.Year = cal.GetYear(dateTimeNow);
          result.Month = cal.GetMonth(dateTimeNow);
          result.Day = cal.GetDayOfMonth(dateTimeNow);
          }
          }
          else
          {
          result.Month = 1;
          result.Day = 1;
          }
          }
          else
          {
          if (result.Year == -1)
          result.Year = cal.GetYear(dateTimeNow);
          if (result.Month == -1)
          result.Month = 1;
          if (result.Day == -1)
          result.Day = 1;
          }
          }
          if (result.Hour == -1)
          result.Hour = 0;
          if (result.Minute == -1)
          result.Minute = 0;
          if (result.Second == -1)
          result.Second = 0;
          if (result.era == -1)
          result.era = 0;
          return true;
          }





          share|improve this answer























          • Yes, I am aware it could be done like this. However string mangling is fragile, and if it's used this way it completely nullifies the point of using DateTime.ParseExact (that is, to not mangle strings yourself), which means I'd be better just parse the components myself.
            – user2988819
            Nov 20 at 4:35










          • @user2988819 sure you could parse it your self, and create a datetime out of it, however in the end you are going to have to make the year a leap year for those special cases
            – TheGeneral
            Nov 20 at 4:38










          • @TheGeneral I'm currently storing the birthday with a dummy leap year anyway. However there are no ways to supply a default year when doing DateTime.ParseExact, which is really a bummer, especially when there is already a DateTimeStyles that sets the default year to something other than the current year.
            – user2988819
            Nov 20 at 4:41






          • 2




            @user2988819 would you believe me if i said you cant?
            – TheGeneral
            Nov 20 at 4:52






          • 3




            Your question does not make sense, that's why you've got so many downvotes and repeated comments. A day and a month does not make a date - therefor they can't be parsed as a DateTime value without assuming a year. The .Net framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption. The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate.
            – Zohar Peled
            Nov 20 at 7:23














          2












          2








          2






          This question lacks the appropriate details, however



          If you just want to parse a birth date and month including leap year dates, then just added a leap year to the end of the date.



          I am not sure what you expect to do here, however you could try this



          birthday = $"{birthday}/2016"; // leap year

          DateTime.TryParseExact(birthday, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate);


          Update




          my question is how to not make TryParseExact assume the year
          automatically by manually overriding it in some way




          To be technical here, no you have to specify the leap year in the string if you are parsing a leap year month and day exclusively as in your example



          There is a lot of checks and balances the TryParseExact method does, however here are the important bits.



          In short, it uses the current year or year 1, and there is no way to tell it to choose a leap year specifically



          private static bool CheckDefaultDateTime(ref DateTimeResult result, ref Calendar cal, DateTimeStyles styles)
          {
          if ((result.flags & ParseFlags.CaptureOffset) != (ParseFlags) 0 && (result.Month != -1 || result.Day != -1) && ((result.Year == -1 || (result.flags & ParseFlags.YearDefault) != (ParseFlags) 0) && (result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags) 0))
          {
          result.SetFailure(ParseFailureKind.Format, "Format_MissingIncompleteDate", (object) null);
          return false;
          }
          if (result.Year == -1 || result.Month == -1 || result.Day == -1)
          {
          DateTime dateTimeNow = DateTimeParse.GetDateTimeNow(ref result, ref styles);
          if (result.Month == -1 && result.Day == -1)
          {
          if (result.Year == -1)
          {
          if ((styles & DateTimeStyles.NoCurrentDateDefault) != DateTimeStyles.None)
          {
          cal = GregorianCalendar.GetDefaultInstance();
          result.Year = result.Month = result.Day = 1;
          }
          else
          {
          result.Year = cal.GetYear(dateTimeNow);
          result.Month = cal.GetMonth(dateTimeNow);
          result.Day = cal.GetDayOfMonth(dateTimeNow);
          }
          }
          else
          {
          result.Month = 1;
          result.Day = 1;
          }
          }
          else
          {
          if (result.Year == -1)
          result.Year = cal.GetYear(dateTimeNow);
          if (result.Month == -1)
          result.Month = 1;
          if (result.Day == -1)
          result.Day = 1;
          }
          }
          if (result.Hour == -1)
          result.Hour = 0;
          if (result.Minute == -1)
          result.Minute = 0;
          if (result.Second == -1)
          result.Second = 0;
          if (result.era == -1)
          result.era = 0;
          return true;
          }





          share|improve this answer














          This question lacks the appropriate details, however



          If you just want to parse a birth date and month including leap year dates, then just added a leap year to the end of the date.



          I am not sure what you expect to do here, however you could try this



          birthday = $"{birthday}/2016"; // leap year

          DateTime.TryParseExact(birthday, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate);


          Update




          my question is how to not make TryParseExact assume the year
          automatically by manually overriding it in some way




          To be technical here, no you have to specify the leap year in the string if you are parsing a leap year month and day exclusively as in your example



          There is a lot of checks and balances the TryParseExact method does, however here are the important bits.



          In short, it uses the current year or year 1, and there is no way to tell it to choose a leap year specifically



          private static bool CheckDefaultDateTime(ref DateTimeResult result, ref Calendar cal, DateTimeStyles styles)
          {
          if ((result.flags & ParseFlags.CaptureOffset) != (ParseFlags) 0 && (result.Month != -1 || result.Day != -1) && ((result.Year == -1 || (result.flags & ParseFlags.YearDefault) != (ParseFlags) 0) && (result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags) 0))
          {
          result.SetFailure(ParseFailureKind.Format, "Format_MissingIncompleteDate", (object) null);
          return false;
          }
          if (result.Year == -1 || result.Month == -1 || result.Day == -1)
          {
          DateTime dateTimeNow = DateTimeParse.GetDateTimeNow(ref result, ref styles);
          if (result.Month == -1 && result.Day == -1)
          {
          if (result.Year == -1)
          {
          if ((styles & DateTimeStyles.NoCurrentDateDefault) != DateTimeStyles.None)
          {
          cal = GregorianCalendar.GetDefaultInstance();
          result.Year = result.Month = result.Day = 1;
          }
          else
          {
          result.Year = cal.GetYear(dateTimeNow);
          result.Month = cal.GetMonth(dateTimeNow);
          result.Day = cal.GetDayOfMonth(dateTimeNow);
          }
          }
          else
          {
          result.Month = 1;
          result.Day = 1;
          }
          }
          else
          {
          if (result.Year == -1)
          result.Year = cal.GetYear(dateTimeNow);
          if (result.Month == -1)
          result.Month = 1;
          if (result.Day == -1)
          result.Day = 1;
          }
          }
          if (result.Hour == -1)
          result.Hour = 0;
          if (result.Minute == -1)
          result.Minute = 0;
          if (result.Second == -1)
          result.Second = 0;
          if (result.era == -1)
          result.era = 0;
          return true;
          }






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 20 at 5:39

























          answered Nov 20 at 4:28









          TheGeneral

          27k63163




          27k63163












          • Yes, I am aware it could be done like this. However string mangling is fragile, and if it's used this way it completely nullifies the point of using DateTime.ParseExact (that is, to not mangle strings yourself), which means I'd be better just parse the components myself.
            – user2988819
            Nov 20 at 4:35










          • @user2988819 sure you could parse it your self, and create a datetime out of it, however in the end you are going to have to make the year a leap year for those special cases
            – TheGeneral
            Nov 20 at 4:38










          • @TheGeneral I'm currently storing the birthday with a dummy leap year anyway. However there are no ways to supply a default year when doing DateTime.ParseExact, which is really a bummer, especially when there is already a DateTimeStyles that sets the default year to something other than the current year.
            – user2988819
            Nov 20 at 4:41






          • 2




            @user2988819 would you believe me if i said you cant?
            – TheGeneral
            Nov 20 at 4:52






          • 3




            Your question does not make sense, that's why you've got so many downvotes and repeated comments. A day and a month does not make a date - therefor they can't be parsed as a DateTime value without assuming a year. The .Net framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption. The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate.
            – Zohar Peled
            Nov 20 at 7:23


















          • Yes, I am aware it could be done like this. However string mangling is fragile, and if it's used this way it completely nullifies the point of using DateTime.ParseExact (that is, to not mangle strings yourself), which means I'd be better just parse the components myself.
            – user2988819
            Nov 20 at 4:35










          • @user2988819 sure you could parse it your self, and create a datetime out of it, however in the end you are going to have to make the year a leap year for those special cases
            – TheGeneral
            Nov 20 at 4:38










          • @TheGeneral I'm currently storing the birthday with a dummy leap year anyway. However there are no ways to supply a default year when doing DateTime.ParseExact, which is really a bummer, especially when there is already a DateTimeStyles that sets the default year to something other than the current year.
            – user2988819
            Nov 20 at 4:41






          • 2




            @user2988819 would you believe me if i said you cant?
            – TheGeneral
            Nov 20 at 4:52






          • 3




            Your question does not make sense, that's why you've got so many downvotes and repeated comments. A day and a month does not make a date - therefor they can't be parsed as a DateTime value without assuming a year. The .Net framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption. The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate.
            – Zohar Peled
            Nov 20 at 7:23
















          Yes, I am aware it could be done like this. However string mangling is fragile, and if it's used this way it completely nullifies the point of using DateTime.ParseExact (that is, to not mangle strings yourself), which means I'd be better just parse the components myself.
          – user2988819
          Nov 20 at 4:35




          Yes, I am aware it could be done like this. However string mangling is fragile, and if it's used this way it completely nullifies the point of using DateTime.ParseExact (that is, to not mangle strings yourself), which means I'd be better just parse the components myself.
          – user2988819
          Nov 20 at 4:35












          @user2988819 sure you could parse it your self, and create a datetime out of it, however in the end you are going to have to make the year a leap year for those special cases
          – TheGeneral
          Nov 20 at 4:38




          @user2988819 sure you could parse it your self, and create a datetime out of it, however in the end you are going to have to make the year a leap year for those special cases
          – TheGeneral
          Nov 20 at 4:38












          @TheGeneral I'm currently storing the birthday with a dummy leap year anyway. However there are no ways to supply a default year when doing DateTime.ParseExact, which is really a bummer, especially when there is already a DateTimeStyles that sets the default year to something other than the current year.
          – user2988819
          Nov 20 at 4:41




          @TheGeneral I'm currently storing the birthday with a dummy leap year anyway. However there are no ways to supply a default year when doing DateTime.ParseExact, which is really a bummer, especially when there is already a DateTimeStyles that sets the default year to something other than the current year.
          – user2988819
          Nov 20 at 4:41




          2




          2




          @user2988819 would you believe me if i said you cant?
          – TheGeneral
          Nov 20 at 4:52




          @user2988819 would you believe me if i said you cant?
          – TheGeneral
          Nov 20 at 4:52




          3




          3




          Your question does not make sense, that's why you've got so many downvotes and repeated comments. A day and a month does not make a date - therefor they can't be parsed as a DateTime value without assuming a year. The .Net framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption. The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate.
          – Zohar Peled
          Nov 20 at 7:23




          Your question does not make sense, that's why you've got so many downvotes and repeated comments. A day and a month does not make a date - therefor they can't be parsed as a DateTime value without assuming a year. The .Net framework assumes a year that is either the current year or year 1 - exactly because 2/29 is valid only on leap years - and this is a very reasonable assumption. The .Net framework does not provide a built in way to store Day/Month values, but Noda Time does - Take a look at AnnualDate.
          – Zohar Peled
          Nov 20 at 7:23


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53386081%2fparsing-leap-year-day-without-year-always-fails-in-c-sharp%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

          Alcedinidae

          RAC Tourist Trophy