decimal.parse fails for currency string created with String.Format? - asp.net

I have a field that I display via:
String.Format({0:c},amount)
This produces the string "$28.28"
However, when I try to convert back to a decimal amount, I get an incorrect format exception:
amount = Decimal.Parse(amount.Text, NumberStyles.Currency)
I also tried it with NumberStyles.AllowCurrencySymbol with the same results. I verified that the value in amount.Text is "$28.28".
Am I missing something? Shouldn't these two operations use the same currency symbol and formats?

var amount = decimal.Parse("$28.28", NumberStyles.Currency);
works fine for me. Make sure your input string is what you think it is.

Are these on different machines?
The machines be be setup differently.
The default formats are set in the control panel regional settings.

Related

How can I get SignalR to stop changing my date/time values?

I have a simple class that contains a DateTime property. When I set the value of this property using DateTime.Now() the value is correct. However, when I pass this class object as a parameter via SignalR, on the receiving end SignalR has changed the DateTime so that it no longer matches the original DateTime. How can I get SignalR to stop manipulating my DateTime values? This issue seems to have started with a recent update to the latest SignalR nuget packages.
This seems to be a problem when the hub and the client are in two different time zones. It seems Microsoft is trying to help, by adjusting the date/time to the local time zone, but I want the original value, not the value Microsoft "thinks" I want.
When you want two systems to communicate with each other I would recommend using always the DateTime in UTC for various reasons. In your case you have two options here:
1 - Send the date as string string date = DateTime.Now.ToString(CultureInfo.InvariantCulture); so on the client side you just need to parse the datetime like DateTime.Parse(date, CultureInfo.InvariantCulture);.
2 - Send the date in UTC like DateTime.UtcNow; so event if the SignalR tries to change the date, it will have the DateTime.Kind as UTC. In this case or you will get the current date correctly, or you just adjust on the client side to the local time like receivedDate.ToLocalTime();
This one was a real head scratcher as I had the exact same issue. The client was storing the correct time but by the time it hit the Hub... it had changed. I'm really glad you posted this as I wouldn't have imagined this issue being possible. #Kiril1512 posted the correct resolution. In my case I used his second option as I didn't want to change my model... although simply converting to a string would have been simpler. While I did follow his suggestion and convert everything to DateTime.UtcNow()... I am thinking this was unnecessary as I noticed even previously stored dates converted correctly. This makes me think that either this isn't necessary to do, or dates are converted to Utc when they hit the Hub automatically which may be what the issue was to begin with?
Either way I posted this as I discovered that converting this date back to Local time was a little more involved. Here is how I ended up doing the conversion which resolved this issue for me that I gathered from this resource:
DateTime convertedDate = DateTime.SpecifyKind(
DateTime.Parse(msg.CreatedOn.ToString()),
DateTimeKind.Utc);
var kind = convertedDate.Kind;
DateTime dt = convertedDate.ToLocalTime();

Why does Win32_Product.InstallDate2 always return null when using WMI?

UPDATE: If you want to help test this quickly in your locale. Launch PowerShell (hold down the Windows key, tap R, release the Windows key, type in "powershell" and press OK) and run this
command - (is the InstallDate2 column empty? Please let us know what you see.):
Get-WmiObject Win32_Product | Format-Table -Property InstallDate, InstallDate2, Name
I should start by saying that this issue is not critical for me (yet), but I am baffled. I am accessing the WMI object Win32_Product, and there are two properties related to dates: InstallDate and InstallDate2 respectively.
InstallDate seems to be a string representation of a DateTime value without the time part. Sort of a cut-off UTC format. Example: 20170819. The field is a string value, and not a DateTime format.
InstallDate2 is supposed to be in real DateTime format, but it is consistently null for all Win32_Product items on all my systems (Windows 7, Windows 10, various editions).
Using WMIExplorer.exe I see this description of InstallDate: "...the InstallDate property has been deprecated in favor of the InstallDate2 property which is of type DateTime rather than String. New implementations should use the InstallDate2 property."
As stated I get null back on all my machines, so I was assuming that InstallDate2 was simply not implemented properly, but then I found this article: Working with Software Installations. This article clearly shows InstallDate2 returning a WMI DateTime (with missing time part?): InstallDate2 = 20060506000000.000000-000.
I am simply wondering what can be causing this InstallDate2 null value on all my systems when I see it working on other systems? Some possibilities that has crossed my mind (one more far fetched than the next perhaps):
OS issue? I don't have access to older OSs, but I see null on several different editions (home, ulitmate, etc...) of Windows 7 and Windows 10 systems. Perhaps it worked on XP and older? I find this unlikely.
Locale issue? I am in a Norwegian locale. Could this affect things? I tried briefly to change the locale on a Windows 10 system, but it had some language pack issues and the result was the same.
Domain (network) issue? Is it conceivable that machines in workgroups work differently than machines that are part of a domain?
Patch level? Could a recent Windows Update have changed something in WMI?
What else could conceivably affect this?
And a second part of the question (in addition to what the cause of the null value for InstallDate2 is). The string I get back for InstallDate (the string format date): 20170819. I am assuming this is just a chopped of version of Universal Time Coordinate (UTC) format. And that it is a locale-independent format? It seems like it when I read about CIM_DATETIME.
I tried filling the rest of the chopped off date string with zeros and passing it to a SWbemDateTime scripting object, and it seemed to work, but that really smells as a "solution". Doesn't seem reliable at all:
Set dateTime = CreateObject("WbemScripting.SWbemDateTime")
dateTime.Value = "20170601000000.000000+000"
MsgBox dateTime.Year
MsgBox dateTime.UTC
It shows 2017 for year, and 0 for UTC. With such a "solution" I obviously really want to get the InstallDate2 DateTime field working correctly so I get a proper Datetime back.
So in all its verbosity, basically a two-part question:
What could be causing Win32_Product.InstallDate2 to consistently report null seemingly only on my systems?
The short string returned by InstallDate - is this in a locale-independent format?
Since I am in a Norwegian locale and see what looks like an English style format, it would seem that it is? Since the field is just a string, the content could basically be "anything" though.
It would be great if someone in another locale could verify that the format returns as: Win32_Product.InstallDate = yyyymmdd.
Reading about CIM_DATETIME seems to indicate the string is locale-independent (even if chopped off).
If you want to test, the quickest way is probably using wbemtest.exe (or better yet PowerShell if you have it available on your box - as mentioned by JosefZ in the comment below):
Launch wbemtest.exe (Hold down the Windows key, tap R, release the Windows key, type in "wbemtest.exe" and press OK).
Click "connect" and then OK (namespace defaults to root\cimv2), and click "connect" again.
Click "Query" and type in this WQL command: SELECT Name,InstallDate2 FROM Win32_Product and click "Use" (or equivalent).
Double click any entry returned, and check InstallDate2 in the middle list box (scroll down).
In my opinion you won't get a full date-time back. The only information available is effectively from MsiGetProductInfo (...INSTALLPROPERTY_INSTALLDATE....). This format is YYYYMMDD. You're only ever going to get the data because that seems to all there is. Note that the documentation for INSTALLPROPERTY_INSTALLDATE says that it is the installation date only if there has been no other servicing since the product was installed, so it appears that you can't even rely on it being the date the product was installed.
See Detecting the time when the program was installed
I suspect the best way to get the time the product was installed is to get the local package path with MsiGetProductInfo (Ex) ...INSTALLPROPERTY_LOCALPACKAGE... and get the cached MSI's CreationDate.

moment.js from now is reporting different results in firefox/ie then chrome

We and foolishly assumed a block of momentjs code would work in all browsers. Right now its correctly working in chrome, but all other browsers its not applying the UTC offset. How do I make this code work consistently in other browsers? Right now chrome is working, all others are not.
new moment(new Date(date)).fromNow();
//below shows an example of an exact date.
var now = new moment(new Date("2013-09-30T23:33:36.937")).fromNow();
In chrome you would see something like "now", all other browsers you would see "in 4 hours"
The way to get it to work:
var now = moment.utc("2013-10-01T13:15:30.937").fromNow();
Note that if you turn it into a "Date" and call moment.utc
var now = moment.utc(new Date("2013-10-01T13:15:30.937")).fromNow();
It will not work. It makes sense now that I think of it.
Original Answer
Try this:
var now = moment(date).fromNow();
But rutter is correct that you should specify either a Z or an offset like -07:00. From .net, you should make sure you use either a DateTime with .Kind set to Utc, or use a DateTimeOffset field.
Expanded Answer
You should understand that when you send a string of 2013-10-01T13:15:30.937, you are not sending any context with it. There is no way to know from that string alone whether the time is at UTC, or in your server's time zone, or in the browser's time zone.
If you pass it directly to moment("2013-10-01T13:15:30.937"), it is going to assume the context of the browser's local time zone.
As you discovered, you can tell moment explicitly that this time is in UTC by using the .utc function, such as moment.utc("2013-10-01T13:15:30.937").
While this will work, there are good reasons not to rely on that alone. For example, what if you ever use the same server API for another application, or perhaps for third-parties to consume? Unless you tell them separately that the timestamp is meant to represent UTC, then there is no way to know that.
These strings are in the ISO 8601 / RFC 3339 format. Part of that specification describes how to indicate that a timestamp is in UTC. You simply add a Z at the end. If you supply the Z then any consumer of this timestamp will know that the time should be interpreted as UTC. And sure enough, if you pass that into moment directly, such as moment("2013-10-01T13:15:30.937Z"), it will give the result you expected.
You said in comments that you were generating these values from ASP.Net Web API. Run your application in debug mode and set a breakpoint so you can examine the output of your controller. When you look at the specific DateTime property in question, you will see that it has its own .Kind property. It is probably set to DateTimeKind.Unspecified.
Since you said specifically that your application uses UTC, then these values should have DateTimeKind.Utc instead. Once that is set, then WebAPI will properly emit the Z at the end of the timestamp.
Somewhere in your server-side code, you should do something like this:
dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
You should do this as early as possible. For example, in your data access layer when you retrieve the value from the database. If that's not possible, then at least you should do it in your API Controller so the value gets emitted properly.
See also the MSDN reference for DateTimeKind and DateTime.SpecifyKind.
Also - the reason you were getting browser inconsistencies is because you were using the Date object's constructor instead of the parsing functions built in to moment. While moment will accept a Date, there are several known problems and inconsistencies with how browsers support parsing a Date from a string. Some of those inconsistencies are documented here.
Use this:
var lastLoginTime = moment(user.lastLoginTime).fromNow();

SQLDataSource parameter insertion: Sanitisation and formatting

I am building a Web application and I want to allow users to insert records into a database. The method that I came across is to take the information from text boxes and run this code:
SqlDataSource1.InsertParameters["ProductCode"].DefaultValue = txtProductCode.Text;
SqlDataSource1.InsertParameters["Name"].DefaultValue = txtName.Text;
SqlDataSource1.InsertParameters["Version"].DefaultValue = txtVersion.Text;
SqlDataSource1.InsertParameters["ReleaseDate"].DefaultValue = txtReleaseDate.Text;
try
{
SQLDataSource1.Insert();
}
...
If I try to inject some SQL I get the error message:
Message: String or binary data would be truncated. The statement has been terminated.
Does this method sanitise the parameters? I am having a hard time finding this information because I am not sure if there is still a way to get around this error. If it does not how should I go about sanitising the inputs?
Additionally, the ReleaseDate parameter seems to be currently reading as dd/MM/yyyy but is there a way to lock this so that the same code on a different system doesn't behave differently. I am worried that if the code is run on a system with different regional settings it will use a different format.
One of your field in the table is not long enough to insert the value. You need to check each of ProductionCode, name, Version and ReleaseDate for their length and increase them accordingly.
http://msdn.microsoft.com/en-us/library/aa196741(v=sql.80).aspx

How can I make input fields accept locale dependent number formatting?

I'm working on a Spring MVC Project and ran into a problem with the internationalization in forms, especially the number formatting.
I already use fmt:formatNumber to format the numbers according to the current selected locale.
<fmt:formatNumber value="${object[field]}"/>
Like this, number formatting works well when I display numbers. But how about the forms?
At the moment, the input fields that are supposed to receive float values are prefilled with 0.0 and expect me to use "." as decimal separator, no matter what locale is selected. Values containing "," are refused by the server (...can not convert String to required type float...).
How can I make my input fields use and accept the appropriate number format as well?
Did you have a look at #NumberFormat? If you annotate the property the input field is bound to, this should result in the proper formatting. Something like:
#NumberFormat(style = Style.NUMBER)
private BigDecimal something;
This style is the "general-purpose number format for the current locale". I guess, the current locale is determined threadwise from the LocaleContextHolder.
Your app needs to be annotation-driven, also see the section "Annotation-driven Formatting" in the docs.
You might want to take a look at the DecimalFormatSymbols as suggested in this answer.

Resources