Home > OS >  Parsing horrible timestamp C#
Parsing horrible timestamp C#

Time:05-08

I have a timestamp from a server of the form 20220505 17:36:29 - it has 2 whitespaces, and I do not trust the sender to always send the same number of whitespaces in future revisions - ideally would like to handle any number of whitespaces the same.

I tried this with DateTime.ParseExact but failed:

var horribleTimestamp = "20220505  17:36:29";
var timestamp = DateTime.ParseExact(horribleTimestamp, "yyyyMMdd  hh:mm:ss", CultureInfo.InvariantCulture)
// throws `System.FormatException: String '20220505  17:36:29' was not recognized as a valid DateTime.`

To save my headaches with timezones later how can I achieve this with Nodatime as i think makes sense to switch to that already.

The time is local from my PC and I would like to convert this to a global timestamp (which I believe should be Instant?) for a given local timezone?

CodePudding user response:

You have an error in your format. use HH instead of hh. See updated code below

var horribleTimestamp = "20220505  17:36:29";
var timestamp = DateTime.ParseExact(horribleTimestamp, "yyyyMMdd  HH:mm:ss", CultureInfo.InvariantCulture)

Here is y link that explains what you can use in a format -> https://www.c-sharpcorner.com/blogs/date-and-time-format-in-c-sharp-programming1

CodePudding user response:

You can pass multiple formats to ParseExact as an array

var horribleTimestamp = "20220505  17:36:29";
var formats = new[]{"yyyyMMdd HH:mm:ss","yyyyMMdd  HH:mm:ss","yyyyMMdd   HH:mm:ss"};
var timestamp = DateTime.ParseExact(horribleTimestamp, formats, CultureInfo.InvariantCulture, 0);

dotnetfiddle

CodePudding user response:

You can solve the problem with the whitespaces in this way:

var horribleTimestamp = "20220505  17:36:29";
var date = horribleTimestamp.Substring(0, 8);
var index = horribleTimestamp.LastIndexOf(' ')   1;
var time = horribleTimestamp.Substring(index, horribleTimestamp.Length - index);
var timestamp = DateTime.ParseExact($"{date} {time}", "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture);

I suppose that date has always 8 characters and that space is always present. In other case, check index == -1.

CodePudding user response:

If you want to handle any amount of whitespace, there are two options:

  • Use a regular expression (or similar) to get it into a canonical format with a single space
  • Split on spaces and then parse the first and last parts separately. (Or split on spaces, recombine the first and last parts and parse...)

In Noda Time, the value you've got represents a LocalDateTime, so that's what you should parse it to. Here's a complete example using the regex approach:

using NodaTime;
using NodaTime.Text;
using System.Text.RegularExpressions;

// Lots of spaces just to check the canonicalization
string text = "20220505     17:36:29";

// Replace multiple spaces with a single space.
string canonicalized = Regex.Replace(text, "  ", " ");

// Note: patterns are immutable; you should generally store them in
// static readonly fields. Note that "uuuu" represents an absolute year number,
// whereas "yyyy" would be "year of era".
LocalDateTimePattern pattern =
    LocalDateTimePattern.CreateWithInvariantCulture("uuuuMMdd HH:mm:ss");

ParseResult<LocalDateTime> result = pattern.Parse(canonicalized);
// Note: if you're happy with an exception being thrown on a parsing failure,
// juse use result.Value unconditionally. The approach below shows what to do
// if you want to handle parse failures without throwing an exception (or with
// extra behavior).
if (result.Success)
{
    LocalDateTime value = result.Value;
    Console.WriteLine(value);
}
else
{
    // You can also access an exception with more information
    Console.WriteLine("Parsing failed");
}
  • Related