Resolved Date Formatting

C# learner

Active member
Joined
Dec 22, 2022
Messages
40
Programming Experience
Beginner
The GEDCOM file that I'm working on downloads dates in many different formats, MM/DD/YYYY, YYYY, MM/YYYY, DD Jun YYYY, etc. I created a routine I thought could handle this but the return goes back without changing. Is there a simpler way of doing this or where is the problem?
C#:
static string newDate (string fDate)
{
    string inputFormatMMDDYYYY = "MM/dd/yyyy";
    string inputFormatDDMONYYYY = "dd MMM yyyy";
    string inputFormatMMYYYY = "MM/yyyy";
    string outputFormat = "yyyy/dd/MM";

    if (fDate.Length == 4)
    {
        return fDate;
    }
    else if (fDate.Length == 10)
    {
        DateTime date = DateTime.ParseExact(fDate, inputFormatMMDDYYYY, CultureInfo.InvariantCulture);
        return fDate = date.ToString(outputFormat);
    }
    else if (fDate.Length == 11)
    {
        DateTime date = DateTime.ParseExact(fDate, inputFormatDDMONYYYY, CultureInfo.InvariantCulture);
        return fDate = date.ToString(outputFormat);
    }
    else if (fDate.Length == 7)
    {
        DateTime date = DateTime.ParseExact(fDate, inputFormatMMYYYY, CultureInfo.InvariantCulture);
        return fDate = date.ToString(outputFormat);
    }
    else
    {
        return fDate;
    }
}
 
Last edited by a moderator:
Have you actually debugged your code? I'd wager not. If you're getting out exactly what you put in then that suggests that either you're matching on the first if conditions or none of them and you're hitting the else block. The debugger will tell you whether that is the case and you can actually look at the input to see what it contains and what its actual Length is. That's why VS has a debugger. You should also have set up test cases that will run your code on multiple valid and invalid inputs to see what happens and whether it's what you expect.
 
BTW, I have fixed the formatting of your code snippet by removing the leading whitespace, which you left on all but the first line. You're far from the only person who does that but it really infuriates me, as though removing whitespace from line but not many others is a good idea. The site code editor can generally fix that and other formatting issues for you when you select all the text and press Shift+Tab. You shouldn't be copying that whitespace in the first place though, given that VS allows you to select an arbitrary block of text by holding down the Alt key.
 
I just copied your method into a project and tested it with this code:
C#:
Console.WriteLine(newDate("2023"));
Console.WriteLine(newDate("01/29/2023"));
Console.WriteLine(newDate("29 Jan 2023"));
Console.WriteLine(newDate("01/2023"));
Console.WriteLine(newDate("Jan 29, 2023"));
and this was the output I got:
2023
2023/29/01
2023/29/01
2023/01/01
Jan 29, 2023
Clearly, your code works exactly as it's supposed to and you simply haven't tested or debugged it properly.
 
I would implement that functionality a bit differently too:
C#:
static string ConvertDateFormat(string dateText)
{
    var knownFormats = new[]
                       {
                           "MM/dd/yyyy",
                           "dd MMM yyyy",
                           "MM/yyyy"
                       };

    if (DateTime.TryParseExact(dateText,
                               knownFormats,
                               CultureInfo.InvariantCulture,
                               DateTimeStyles.None,
                               out var date))
    {
        return date.ToString("yyyy/dd/MM");
    }

    return dateText;
}
Note that the method name is descriptive of the purpose and, as is the common convention in C#, starts with an upper-case letter. The code then tries to parse the input based on the known formats and formats the result if successfull, otherwise returns the input.
 
Notes:


This works because assignment in c# results in a value:

C#:
        return fDate = date.ToString(outputFormat);

The date is turned to a string by the ToString call. The result of the ToStribg is assigned to fDate. Assignment results in a value, which is returned

It's a very odd pattern; it works, but it's atypical to write like this. This would be more expected:

C#:
        return date.ToString(outputFormat);

You don't need to assign the value that ToString generates, to anything, to be able to return it. You can just return <some value you generate>

However, while we're at it we might as well also do away with the temporary variable too:

C#:
 return DateTime.ParseExact(fDate, inputFormatMMDDYYYY, CultureInfo.InvariantCulture).ToString(outputFormat);


Assignment resulting in a value is useful occasionally. It allows constructs like this:

C#:
while(line = reader.ReadLine() != null)

reader.ReadLine returns null when it is done reading, otherwise it reads a line from (e.g. a file). Whether it returns a string of text or a null, we capture that into the variable line by assignment. That assignment returns the value that was assigned, which we compare with null to generate a bool that dictates if the loop runs or not

It's also common in setting multiple things to the same value:

C#:
  a=b=c=1;

c is assigned 1, and this results in 1 which is assigned to b, and this results in 1 which is assigned to a..

What do you suppose the results are here, if immediately after that line of code above we do:

C#:
  a+=b+=c+=1;

Can you work out why a is 4?

---

Though it's a valid use case and syntax, "assignment returns the value assigned" is one of those nuances of C# that is easy to forget, so it's say "avoid using it if you can" and definitely in the case you wrote
 
Last edited:
OK, I inserted the code (by the way thank you for showing the proper way). I added to the format list "yyyy" because the first date is 1788. I debugged through the new code and when it got back to to the method call it was the same thing 1788.

birthDate = (line != null && tag == "DATE" && individualInfo != null) ? individualInfo : " ";
ConvertDateFormat(birthDate);

Now I understand that because it this example is not a very good example. So I looked at other dates.
From the origin file: 10/26/1890
After debug: 10/26/1890

From the origin file: 13 Jun 1849
After debug: 13 Jun 1849

Is there something wrong with the method call?
 
Show us how you are calling the method.
 
OK, I inserted the code (by the way thank you for showing the proper way). I added to the format list "yyyy" because the first date is 1788. I debugged through the new code and when it got back to to the method call it was the same thing 1788.

birthDate = (line != null && tag == "DATE" && individualInfo != null) ? individualInfo : " ";
ConvertDateFormat(birthDate);
It appears that you are expecting the method to change the value of the variable you pass in. That's not going to happen because that's not how you or I wrote the method. Try this:
C#:
var input = "10/26/1890";
var output = ChangeDateFormat(input);
and then look at the values of input and output. The former has not changed while the latter contains the converted value. Notice that, in my examples earlier, I was displaying the result of the call and there was no input variable; only literals. If you wanted to change the original variable with that method then you'd have to assign the result of the call back to that variable, e.g.
C#:
var input = "10/26/1890";

input = ChangeDateFormat(input);
If you expected the variable to change without that assignment then you'd have to declare the parameter ref and set it within the method. Maybe that's what you were trying to do with those odd return statements (which I didn't even notice) but, without a ref parameter, they would have no effect. It would be inappropriate to use a ref parameter in this case though.
 
Not sure how these posts and code are to be formatted so bear with me.
I'm not sure where to put/insert the code:
var input = "10/26/1890";
var output = ChangeDateFormat(input);
you gave me? At the call to method or at the method? Only been at C# for maybe 3 months.
 
At the call to the method. The point was to demonstrate that input won't change, but the return value will be stored in output.
 
Ok, finally got it through my head how to do these dates, Thanks

newBirthPlace = ConvertDateFormat(birthPlace);
birthPlace = newBirthPlace;
 
Ok, finally got it through my head how to do these dates, Thanks

newBirthPlace = ConvertDateFormat(birthPlace);
birthPlace = newBirthPlace;
What's the point of the newBirthPlace variable if you're just going to assign it immediately to birthPlace? Why not just assign the method result directly to birthPlace and do away with the extra variable?
 
Back
Top Bottom