Parsing leap year day without year always fails in C#
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
add a comment |
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
add a comment |
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
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
c# datetime
edited Nov 21 at 1:28
asked Nov 20 at 4:08
user2988819
183
183
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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.
Nicely worded and upvoted
– TheGeneral
Nov 20 at 9:39
Noda Time does have parsing forAnnualDate
. It's handled by theAnnualDatePattern
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
add a comment |
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;
}
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 usingDateTime.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 doingDateTime.ParseExact
, which is really a bummer, especially when there is already aDateTimeStyles
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
|
show 13 more comments
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Nicely worded and upvoted
– TheGeneral
Nov 20 at 9:39
Noda Time does have parsing forAnnualDate
. It's handled by theAnnualDatePattern
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
add a comment |
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.
Nicely worded and upvoted
– TheGeneral
Nov 20 at 9:39
Noda Time does have parsing forAnnualDate
. It's handled by theAnnualDatePattern
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
add a comment |
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.
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.
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 forAnnualDate
. It's handled by theAnnualDatePattern
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
add a comment |
Nicely worded and upvoted
– TheGeneral
Nov 20 at 9:39
Noda Time does have parsing forAnnualDate
. It's handled by theAnnualDatePattern
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
add a comment |
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;
}
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 usingDateTime.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 doingDateTime.ParseExact
, which is really a bummer, especially when there is already aDateTimeStyles
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
|
show 13 more comments
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;
}
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 usingDateTime.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 doingDateTime.ParseExact
, which is really a bummer, especially when there is already aDateTimeStyles
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
|
show 13 more comments
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;
}
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;
}
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 usingDateTime.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 doingDateTime.ParseExact
, which is really a bummer, especially when there is already aDateTimeStyles
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
|
show 13 more comments
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 usingDateTime.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 doingDateTime.ParseExact
, which is really a bummer, especially when there is already aDateTimeStyles
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
|
show 13 more comments
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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