views:

331

answers:

3

Hi all,

I am working on re-writing an existing Java software solution in .NET. At one point, the Java solution reads a time stamp at the beginning of a string, simply like this:

SimpleDateFormat dateFormat = new SimpleDateFormat(timeFormat);
dateFormat.setLenient(false);

try
{
    timeStamp = dateFormat.parse(line);
}
catch (ParseException e)
{
    //...
}

Now I am trying to do the same in C#:

DateTimeFormatInfo dateTimeFormatInfo = new DateTimeFormatInfo();
dateTimeFormatInfo.FullDateTimePattern = format;

try
{
    timeStamp = DateTime.Parse(line, dateTimeFormatInfo);
}
catch (FormatException ex)
{
    //...
}

Both languages work until I add some random text after the time stamp in the line variable. Java will just ignore it, but C# will not allow anything else after the time stamp text in the line.

So while Java is happy to parse "01/01/01 01:01:01,001 Hello World!" as a time stamp, C# is not, because " Hello World!" is not specified in the format string.

However, as I cannot make any statement about what might come after the time stamp inside my strings, I cannot include it in my format string.

Any ideas?

Thank you in advance.

A: 

If you know what format your date will be in and the context with which it's stored then that's an advantage.

For instance, if you knew that you were storing yesterday's logs or something like that:

DateTime yesterday = DateTime.Today.AddDays(-1);
timestamp = DateTime.Parse(
    line.SubString(0, line.IndexOf(yesterday.Year.ToString()) + 4));

edit: Is there anything delimiting the text after the date (even a space)?

If there is, you could do something like this:

private static DateTime GetDate(string line)
{
    int index = 0;
    DateTime theDate;
    string s = line;

    while(!DateTime.TryParse(s, out theDate))
    {
        index = line.IndexOf(" ", index);
        s = line.Substring(0, index);
    }

    return theDate;
}

Note: This will fail to get the time if there is text after the date (as it will be able to parse out the date without time successfully when searching). You could fix that by getting the index of spaces starting at the end of the line and moving backward. I'll leave that to you.

SnOrfus
I don't, unfortunately. The time format pattern is given by configuration, but the date could be anything, yesterday, one month ago, one year ago.
Callash
A: 

Looks like .Net is going to parse the whole string and you don't control the whole string. I would say use TryParse() and if it fails, strip off the right-most "word" from your string and re-try. I'm not familiar with Java but it may do this under the covers.

No Refunds No Returns
+1  A: 

Try this:

Dictionary<string, string> tests = new Dictionary<string,string>()
{
    { "yy/MM/dd HH:mm:ss,fff", "01/01/01 01:01:01,001 Hello World!"},
    { "yyyyMMddHHmmssfff", "2009111615413829403 Hello World!"},
    { "d.M.yyyy H:m:s,fff", "8.10.2009 8:17:26,338 Hello World!" }
};

foreach(KeyValuePair<string, string> test in tests)
{
    string pattern = test.Key;
    string format = test.Value;

    DateTimeFormatInfo dateTimeFormatInfo = new DateTimeFormatInfo();
    dateTimeFormatInfo.FullDateTimePattern = pattern;

    Console.WriteLine("{0} - {1}", pattern, format);
    DateTime timeStamp = DateTime.MinValue;
    if (pattern.Contains(' ')) // approach 1: split and conquer
    {
        format = String.Join(" ", format
            .Split(" ".ToCharArray())
            .Take(pattern.Count(c => c == ' ') + 1));
    }
    else
    {
        format = format.Substring(0, pattern.Length);
    }


    if (!DateTime.TryParseExact(
        format, pattern, dateTimeFormatInfo, 
        DateTimeStyles.AllowWhiteSpaces, out timeStamp))
    {
        Console.WriteLine("\tSomething sad happened");
    }
    else
    {
        Console.WriteLine("\t{0}", timeStamp.ToString(pattern));
    }
}
Console.Read();

Note I don't use DateTime.Parse, since it throws an Exception if String isn't a valid DateTime formatted string.

UPDATE 1: Better input handling, as don't expect an whitespace, but uses pattern length

UPDATE 2: Two previous approach merged into this code; I'm aware about using a single d into test #2, but I don't think we can do anything about it.

Rubens Farias
Getting there, but if I see it correctly, this assumes that there is always a whitespace after the time stamp. One line I might come across would look like this: "2009111615413829403" which is "yyyyMMddHHmmssfff" followed by a two-digit error code.
Callash
Still not it, as your solution expects the time pattern and the time stamp to have the same length. My pattern could be "d.M.yyyy H:m:s,fff" (length 18), and the time stamp to parse could be "8.10.2009 8:17:26,338" (length 21).
Callash
you're right; that pattern is always valid?
Rubens Farias
We can assume valid patterns, yes.
Callash