Given the following JSON Date representation:
"\/Date(1221644506800-0700)\/"
How do you deserialize this into it's JavaScript Date-type form?
I've tried using MS AJAX JavaScrioptSerializer as shown below:
Sys.Serialization.JavaScriptSerializer.deserialize("\/Date(1221644506800-0700)\/")
However, all I get back is the literal string date.
Provided you know the string is definitely a date I prefer to do this :
new Date(parseInt(value.replace("/Date(", "").replace(")/",""), 10))
Bertrand LeRoy, who worked on ASP.NET Atlas/AJAX, described the design of the JavaScriptSerializer DateTime output and revealed the origin of the mysterious leading and trailing forward slashes. He made this recommendation:
run a simple search for "\/Date((\d+))\/" and replace with "new Date($1)" before the eval
(but after validation)
I implemented that as:
var serializedDateTime = "\/Date(1271389496563)\/";
document.writeln("Serialized: " + serializedDateTime + "<br />");
var toDateRe = new RegExp("^/Date\\((\\d+)\\)/$");
function toDate(s) {
if (!s) {
return null;
}
var constructor = s.replace(toDateRe, "new Date($1)");
if (constructor == s) {
throw 'Invalid serialized DateTime value: "' + s + '"';
}
return eval(constructor);
}
document.writeln("Deserialized: " + toDate(serializedDateTime) + "<br />");
This is very close to the many of the other answers:
Use an anchored RegEx as Sjoerd Visscher did -- don't forget the ^ and $.
Avoid string.replace, and the 'g' or 'i' options on your RegEx. "/Date(1271389496563)//Date(1271389496563)/" shouldn't work at all.
A JSON value is a string, number, object, array, true, false or null. So this is just a string. There is no official way to represent dates in JSON. This syntax is from the asp.net ajax implementation. Others use the ISO 8601 format.
You can parse it like this:
var s = "\/Date(1221644506800-0700)\/";
var m = s.match(/^\/Date\((\d+)([-+]\d\d)(\d\d)\)\/$/);
var date = null;
if (m)
date = new Date(1*m[1] + 3600000*m[2] + 60000*m[3]);
The regular expression used in the ASP.net AJAX deserialize method looks for a string that looks like "/Date(1234)/" (The string itself actually needs to contain the quotes and slashes). To get such a string, you will need to escape the quote and back slash characters, so the javascript code to create the string looks like "\"\/Date(1234)\/\"".
This will work.
Sys.Serialization.JavaScriptSerializer.deserialize("\"\\/Date(1221644506800)\\/\"")
It's kind of weird, but I found I had to serialize a date, then serialize the string returned from that, then deserialize on the client side once.
Something like this.
Script.Serialization.JavaScriptSerializer jss = new Script.Serialization.JavaScriptSerializer();
string script = string.Format("alert(Sys.Serialization.JavaScriptSerializer.deserialize({0}));", jss.Serialize(jss.Serialize(DateTime.Now)));
Page.ClientScript.RegisterStartupScript(this.GetType(), "ClientScript", script, true);
For those who don't want to use Microsoft Ajax, simply add a prototype function to the string class.
E.g.
String.prototype.dateFromJSON = function () {
return eval(this.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));
};
Don't want to use eval? Try something simple like
var date = new Date(parseInt(jsonDate.substr(6)));
As a side note, I used to think Microsoft was misleading by using this format. However, the JSON specification is not very clear when it comes to defining a way to describe dates in JSON.
Actually, momentjs supports this kind of format, you might do something like:
var momentValue = moment(value);
momentValue.toDate();
This returns the value in a javascript date format
The big number is the standard JS time
new Date(1221644506800)
Wed Sep 17 2008 19:41:46 GMT+1000 (EST)
Related
In the code snippet below, the JSON string in the commented out jsonString variable is valid while the uncommented out one causes JObject.Parse to throw a JsonReaderException with the message:
After parsing a value an unexpected character was encountered: e. Path 'Key', line 1, position 15.
var jsonString = "{\"Key\":\"Value \"extra\" \"}";
//var jsonString = "{\"Key\":\"Value \\\"extra\\\" \"}";
JObject.Parse(jsonString);
Are there any methods available in Newtonsoft.Json or elsewhere that can transform a JSON string to make it valid?
No, because NewtonSoft cannot guess what you want. E.g. is extra a new key and did you just ommit a comma or is it part of the previous value, or is it just something that can be ignored. It would be better to have the thing you are consuming the json from construct valid json.
Using Regex might help you to resolve the existing JSON you have. If you can control how subsequent JSON is generated, you really should fix it at that point.
This solution counts the value as existing from the first " after a "key":, through to the last " before a , or a }, and then it reserializes the value to ensure that it is correctly escaped. If it finds ",, it expects it to be followed by another key ("key":). This is in an attempt to avoid red herrings (i.e. {"key": "test "," value"}) which might otherwise confuse it.
private static string FixJson(string json)
{
var regex = new Regex("\"(?<key>.*?)\"\\W?:\\W?\"(?<value>.*?)\"(?=,\".*?\"\\W?:|}$)");
return regex.Replace(json, new MatchEvaluator(m => {
var key = m.Groups["key"].Value;
var val = m.Groups["value"].Value;
return string.Format("\"{0}\":{1}", key, JsonConvert.SerializeObject(val));
}));
}
Disclaimer: It's a regular expression, it's not foolproof, and if your JSON is more broken than you have indicated, it will probably spit out broken JSON, or incorrect values, so use it at your own risk.
Try it online
Background: We have a system that receives data from another backend system. We handle the displaying of that data, and we have our own XML templates to control how certain things are displayed (i.e. we have our own column templates to dictate what the column headers are, etc.) One thing we would like to support is the ability to provide a mask for these column templates that would apply to the values coming from the backend. Below is a scenario that I'm having trouble with.
Problem: I can't seem to get a simple string format working. I'd like to format a STRING value of four digits (i.e. "1444") in a time format (i.e. "14:44"). I've tried:
String.Format("{0:00:00}", "1444")
Note the importance of the input being a STRING. If I supply an int value, the format will work. The reason I cannot use this is because all the data we receive from the backend is in string format, and we'd like for this to be generic (so casting isn't really an option).
By generic, I mean I'd like to specify a mask in our own XML templates, something like:
<MyColumnTemplate Id="MyColumn" Mask="00:00" />
and to use that mask in a string format call for string values? If the mask fails, we could just simply return the original value (as the String.Format() method already does by default).
Edit: To help clarify, here is a simplified version of what I'd like to be able to do in code:
string inputValue = "1444";
string maskValueFromXml = "00:00";
string mask = "{0:" + maskValueFromXml + "}";
string myDesiredEndResult = String.Format(mask, inputValue);
The thing is you are working string to string,since you ask for time and phone number they are all numbers then try this trick(if we can call it that :)):
string result = string.Format("{0:00:00}", int.Parse("1444"));
For phone number:
string result = string.Format("{0:000-000-0000}", int.Parse("1234560789"));
You can even place your desired masks in a dictionary for example and do this:
Dictionary<string, string> masks = new Dictionary<string, string>();
masks.Add("Phone", "{0:000-000-0000}");
masks.Add("Time", "{0:00:00}");
string test = "1234560789";
string result = string.Format(masks["Phone"], int.Parse(test));
Try with DateTime.TryParseExact, e.g:
DateTime dateEntered;
string input = "1444";
if (DateTime.TryParseExact(input, "HH:mm", System.Globalization.CultureInfo.CurrentCulture, System.Globalization.DateTimeStyles.None, out dateEntered))
{
MessageBox.Show(dateEntered.ToString());
}
else
{
MessageBox.Show("You need to enter valid 24hr time");
}
After that, you can use string.Format, predefined formats on MSDN.
In C#.Net, here's a simple example of how to format numbers into strings using custom format strings:
(example taken from: http://www.csharp-examples.net/string-format-int/)
String.Format("{0:+### ### ### ###}", 447900123456); // "+447 900 123 456"
String.Format("{0:##-####-####}", 8958712551); // "89-5871-2551"
Is there a way to convert this formatted string back into a long/integer ? Is there someway to do this :
long PhoneNumber = Int32.Parse("89-5871-2551", "{0:##-####-####}");
I saw that DateTime has a method ParseExact which can do this work well. But I did not see any such thing for int/long/decimal/double.
You can regex out all of the non numeric numbers, and what you're left with is a string of numbers that you can parse.
var myPhoneNumber = "89-5871-2551";
var strippedPhoneNumber = Regex.Replace(myPhoneNumber, #"[^\d]", "");
int intRepresentation;
if (Int32.TryParse(strippedPhoneNumber, out intRepresentation))
{
// It was assigned, intRepresentation = 8958712551
// now you can use intRepresentation.
} else {
// It was not assigned, intRepresentation is still null.
}
Well, you can always do
long PhoneNumber = Int32.Parse("89-5871-2551".
Replace(new char[]{'-','+',whatever..}).Trim());
By the way, considering that you're parsing a string received from some IO, I would suggest to use more secure (in terms of conversion) Int32.TryParse method.
The way like you described doesn't actually exist.
Just Regex out all of the non-numeric characters, then parse that string.
I have an string like this
string strdate =#"5/2/2006";
Which is in a form of month/day/year.
I need to display it in a form of like this 02-05-2006.
How do i format the data like this?
If the value is like this: 12/28/2005, it should be displayed like this: 28-12-2010.
I know we should be splitting the data based on that we should do it.
I am not getting the syntax how to do it .
Any help would be great.
Parse the string into a DateTime and then use ToString with the right format to output it.
DateTime dt = DateTime.ParseExact(#"5/2/2006",
"MM/dd/yyyy",
CultureInfo.InvariantCulture);
string output = dt.ToString("dd-MM-yyyy");
I suggest reading up on custom and standard date and time format strings.
Read about how to parse DateTime string here: http://msdn.microsoft.com/en-us/library/1k1skd40.aspx
Then you read about how to print it here: http://msdn.microsoft.com/en-us/library/8tfzyc64.aspx
#Kevin
var datearray = strdate.split('/');
string date = datearray[0] + "-" + datearray[1] + "-" datearray[2]
Issue 1
This wont work from days from 10th to 31st... It will add leading zero to each day.
12-05-2010 is good, but for ex. 12-021-2010 is not good.
Issue 2
Wrong order of MM-dd
You can use string.replace as such:
string newString = oldString.Replace('/', '-');
This will replace each '/' with '-' and create a new string, it will not replace it within the old string as strings are immutable.
Is there a way to tell the String.Format() function (without writing my own function) how many placeholders there are dynamically? It we be great to say 15, and know I'd have {0}-{14} generated for me. I'm generate text files and I often have more than 25 columns. It would greatly help.
OK,
I will rephrase my question. I wanted to know if it is at all possible to tell the String.Format function at execution time how many place-holders I want in my format string without typing them all out by hand.
I'm guessing by the responses so far, I will just go ahead and write my own method.
Thanks!
You could use Enumerable.Range and LINQ to generate your message string.
Enumerable.Range(0, 7).Select(i => "{" + i + "}").ToArray()
generates following string:
"{0}{1}{2}{3}{4}{5}{6}"
Adding a bit to AlbertEin's response, I don't believe String.Format can do this for you out-of-the-box. You'll need to dynamically create the format string prior to using the String.Format method, as in:
var builder = new StringBuilder();
for(var i = 0; i < n; ++i)
{
builder.AppendFormat("{0}", "{" + i + "}");
}
String.Format(builder.ToString(), ...);
This isn't exactly readable, though.
Why use string.Format when there is no formatting (atleast from what I can see in your question)? You could use simple concatenation using stringbuilder instead.
There is a way to do this directly:
Just create a custom IFormatProvider, then use this overload of string.Format.
For example, if you want to always have 12 decimal points, you can do:
CultureInfo culture = Thread.CurrentThread.CurrentCulture.Clone(); // Copy your current culture
NumberFormatInfo nfi = culture.NumberFormat;
nfi.NumberDecimalDigits = 12; // Set to 12 decimal points
string newResult = string.Format(culture, "{0}", myDouble); // Will put it in with 12 decimal points