Reputation: 2441
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?
Upvotes: 0
Views: 473
Reputation: 1501656
If you want to handle any amount of whitespace, there are two options:
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");
}
Upvotes: 4
Reputation: 2371
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.
Upvotes: 0
Reputation: 71952
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);
Upvotes: 3