Converting JSON Date & Time to Normal Date & Time in C# [duplicate] - c#

Context
The line JsonConvert.SerializeObject(DateTime.Now) gives the following result:
"2018-05-25T07:59:27.2175427+02:00"
However when I try to deserialize this JSON string to a DateTime with the line: JsonConvert.DeserializeObject<DateTime>("2018-05-25T07:59:27.2175427+02:00")
it gives an Newtonsoft.Json.JsonReaderException with the following message:
Unexpected character encountered while parsing value: 2. Path '', line 1, position 1.
What else I've tried so far
"2018-05-25T07:59:27"
causes the very same exception
Question
Having the datetime string in JSON serialized format, I would like to have a DateTime variable and the correct value in it. How can I accomplish this task?

As shown in the JSON standard, a JSON string literal must be quoted:
A string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes. A character is represented as a single character string. A string is very much like a C or Java string.
Thus, to be valid JSON, your c# string literal must include the surrounding double quotes, like so:
var dateTime = JsonConvert.DeserializeObject<DateTime>("\"2018-05-25T07:59:27.2175427+02:00\"");
It's easy to confuse the outermost quotes, which are part of the c# language and delimit the string in your c# code but are not included in the string itself, with the inner quotes, which are part of the string literal itself.
Sample fiddle here.

The problem is that JsonConvert.DeserializeObject looks like it wants a JSON object rather than just any JSON value. (It's a shame that SerializeObject doesn't always produce an object, but...)
You can parse it like this:
DateTime dt = new JValue("2018-05-25T07:59:27.2175427+02:00").ToObject<DateTime>();
Or (equivalently? I'm not entirely sure):
DateTime dt = (DateTime) new JValue("2018-05-25T07:59:27.2175427+02:00");
There may be a better way of doing so, but that at least works.

Related

What is this C#/.net5 notation called with a colon in a interpolated string?

I came across some notation in an interpolated string currentDate:d in the Microsoft documentation but they do not elaborate on how it works or what it is called, so I don't know how to look it up further. It appears to deconstruct a DateTime and get the date and time specifically, and only seems to work in the interpolated string; I can't use the same trick to pull the time out into a variable. I'm wondering if I can use that notation for other objects and how it works.
var currentDate = DateTime.Now;
var time = currentDate:t; // this throws error
Console.WriteLine($"{Environment.NewLine}It is currently {currentDate:d} at {currentDate:t}!");
outputs:
It is currently 2021-10-31 at 10:41 AM!
MS docs source: https://learn.microsoft.com/en-us/dotnet/core/tutorials/with-visual-studio-code?pivots=dotnet-5-0
I can't think of a better way to ask this question, so would appreciate a hint.
It is explained in the docs that you linked. It says:
The dollar sign ($) in front of a string lets you put expressions such as variable names in curly braces in the string. The expression value is inserted into the string in place of the expression. This syntax is referred to as interpolated strings.
The link there takes you to the page "$ - string interpolation - C# reference", which has a section named "Structure of an interpolated string" that says this:
The structure of an item with an interpolation expression is as follows:
{<interpolationExpression>[,<alignment>][:<formatString>]}
[...]
formatString: A format string that is supported by the type of the expression result. For more information, see Format String Component.
The link "Format String Component" then gives you all the info you need:
The optional formatString component is a format string that is appropriate for the type of object being formatted. Specify a standard or custom numeric format string if the corresponding object is a numeric value, a standard or custom date and time format string if the corresponding object is a DateTime object, or an enumeration format string if the corresponding object is an enumeration value.
[...]
Date and time types: Standard Date and Time Format Strings / Custom Date and Time Format Strings
The linked page "Standard Date and Time Format Strings" explains d as follows:
Format Specifier
Description
Examples
d
Short date pattern. - More information: The short date ("d") format specifier
2009-06-15T13:45:30 -> 6/15/2009 (en-US) [...]
This already explains it in short, but the link provided in the table leads to an even more detailed explanation.
This also shows an example of how to use such a format string outside of an interpolated string, using the ToString method:
DateTime date1 = new DateTime(2008, 4, 10);
Console.WriteLine(date1.ToString("d",
DateTimeFormatInfo.InvariantInfo)); // Displays 04/10/2008
Console.WriteLine(date1.ToString("d",
CultureInfo.CreateSpecificCulture("en-US"))); // Displays 4/10/2008
Console.WriteLine(date1.ToString("d",
CultureInfo.CreateSpecificCulture("en-NZ"))); // Displays 10/04/2008
Console.WriteLine(date1.ToString("d",
CultureInfo.CreateSpecificCulture("de-DE"))); // Displays 10.04.2008
It's just some of the standard date and time format specifiers.
"d" is the short date format specifier, "t" is the short time format specifier.
More info can be found at Standard date and time format strings on MSDocs.
Aside: You could have achieved this without string interpolation as well:
Console.WriteLine("It is currently {0:d} at {0:t}!", currentDate);

How to solve problem of Run time error while using string,Format

I have to map this string by specific format into a property of my dataModel, so I use string.Format() to handle it, but I faced a Run time error that says:
Input string was not in a correct format!!!
how could write it in the correct format?
Value = string.Format("guid{({0})}title{({1})}parameterName{({2})}", retirementItem.Guid, retirementItem.Title, retirementItem.ParameterName)
Use the $ - string interpolation syntax. A more readable and convenient syntax to create formatted strings.
If you dont need curly brackets in your string:
Value = $"guid({retirementItem.Guid})title({retirementItem.Title})parameterName({retirementItem.ParameterName})";
If you need them:
Value = $"guid{{({retirementItem.Guid})}}title{{({retirementItem.Title})}}parameterName{{({retirementItem.ParameterName})}}";
The char { and } are keywords in string.Format.
so you have to escape them using {{ and }} like:
Console.WriteLine(string.Format("guid{{({0})}}title{{({1})}}parameterName{{({2})}}", Guid.NewGuid(), "title", "name"));

Deserialize a single DateTime object with JsonConvert

Context
The line JsonConvert.SerializeObject(DateTime.Now) gives the following result:
"2018-05-25T07:59:27.2175427+02:00"
However when I try to deserialize this JSON string to a DateTime with the line: JsonConvert.DeserializeObject<DateTime>("2018-05-25T07:59:27.2175427+02:00")
it gives an Newtonsoft.Json.JsonReaderException with the following message:
Unexpected character encountered while parsing value: 2. Path '', line 1, position 1.
What else I've tried so far
"2018-05-25T07:59:27"
causes the very same exception
Question
Having the datetime string in JSON serialized format, I would like to have a DateTime variable and the correct value in it. How can I accomplish this task?
As shown in the JSON standard, a JSON string literal must be quoted:
A string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes. A character is represented as a single character string. A string is very much like a C or Java string.
Thus, to be valid JSON, your c# string literal must include the surrounding double quotes, like so:
var dateTime = JsonConvert.DeserializeObject<DateTime>("\"2018-05-25T07:59:27.2175427+02:00\"");
It's easy to confuse the outermost quotes, which are part of the c# language and delimit the string in your c# code but are not included in the string itself, with the inner quotes, which are part of the string literal itself.
Sample fiddle here.
The problem is that JsonConvert.DeserializeObject looks like it wants a JSON object rather than just any JSON value. (It's a shame that SerializeObject doesn't always produce an object, but...)
You can parse it like this:
DateTime dt = new JValue("2018-05-25T07:59:27.2175427+02:00").ToObject<DateTime>();
Or (equivalently? I'm not entirely sure):
DateTime dt = (DateTime) new JValue("2018-05-25T07:59:27.2175427+02:00");
There may be a better way of doing so, but that at least works.

Parsing timestamp containing special characters (quotes)

So, the other day I ran into a problem when trying to parse a timestamp which was wrapped in quotes, it looked like this in the file I was reading:
"2018-04-09"
A C# string with this content:
var dt = "\"2018-04-09\""
I wanted to use DateTime.TryParseExact() to convert the string into a .net DateTime object, without stripping the chars from the string (don't ask why, it's not relevant), but finding a working format string turned out to be tricky.
I read the docs. I googled. Searched StackOverflow. No success.
What format would allow me to parse this timestamp to a DateTime object?
So - the solution, handed to me by a colleague:
var format = "\\\"yyyy-MM-dd\\\"";
If I understand this correctly, the format string is expected to contain a \ which is later resolved to escape the " inside ParseExact(). The first \ escapes the second, the third escapes ", leading to the character sequence \" as part of the format string which is then processed somewhere down the line.
The following works:
var dts = "\"2018-04-09\"";
var format = "\\\"yyyy-MM-dd\\\"";
var dt = DateTime.ParseExact(dts, format, null);
I hope this helps someone!

Surprising int.ToString output

I have been working on a project, and found an interesting problem:
2.ToString("TE"+"000"); // output = TE000
2.ToString("TR"+"000"); // output = TR002
I also have tried with several strings other than "TE" but all have the same correct output.
Out of curiosity, I am wondering how come this could have happened?
Simply based on Microsoft's documentation, Custom Numeric Format Strings, your strings "TE000" and "TR000" are both custom format strings, but clearly they are parsed differently.
2.ToString("TE000") is just a bug in the formatter; it's going down a buggy path because of the unescaped "E". So it's unexpectedly assuming the whole thing is a literal.
2.ToString("TR000") is being interpreted as an implied "TR" literal plus 3 zero-filled digits for an integer value; therefore, you get "TR002".
If you truly want TE and TR verbatim, the expressions 2.ToString("\"TE\"000") and 2.ToString("\"TR\"000") will accomplish that for you by specifying TE and TR as explicit literals, instead of letting the formatter guess if they are valid format specifiers (and getting it wrong).
The ToString needs to PARSE the format string and understand what to do with it.
Let's take a look to the following examples:
2.ToString("TE000"); //output TE000
2.ToString("E000"); //output 2E+000
2.ToString("0TE000); //output 2TE000
2.ToString("T"); //throws exception
2.ToString("TT"); //output TT
This shows that if the ToString parser can understand at least part of the format, it will assume that the rest is just extra characters to print with it. If the format is invalid for the given number (like when you use a DateTime string format on a number), it will throw an exception. If it can not make sense of the format, it will return the format string itself as the result.
You cannot use a numeric format to achieve a custom format, instead use something like this:
int i = 2;
String.Format("TE{0:X3}", i);
See Custom Numeric Format Strings. The E means the exponent part of the scientific notation of the number. Since 2 is 2E000 in exponential notation, that might explain it.

Categories

Resources