C# AddDays throws ArgumentOutOfRangeException when data received is in 24hours format - c#

here's my problem. I am importing an Excel file with a field having a time field. On some servers (french) when I do
double cellValueAsDouble = double.Parse(cellValue.Replace(".", ","));
MyDate.AddDays(cellValueAsDouble);
to add more than 12hours it works. But on an another servers (english) I have an error throwing an ArgumentOutOfRangeException. If I put less than or 12:00:00 it works fine. Does anyone knows why and how I can fix that?

I try to guess the answer:
The cellValue contains a comma as a decimal separator. so it's
value is e.g. 0,5833333333.
You replace the comma with a point => 0.5833333-
Converting this to a double on a french server reveals 58333333333.
Adding this to a date produces the exception.
Your software does not expect a point '.' as the decimal separator, but whatever is configured on the target system. As long as the excel source remains on the same computer, you don't have to exchange anything.
Also, is it really and XLS-format or are you talking about CSV? If your data comes from a french EXCEL exported as CSV, you will end up in having decimal values formatted using a comma. Now you check your software on your local PC (which has US culture I guess) and you are adding the code to replace the comma with a point. Wow, it now works on your PC! But don't expect that same code to work on another machine.
You either have to parse the decimal value manually or just rely that the data source (your EXCEL data) is formatted on a machine having the same culture settings as your the machine running your application.
One guess why values less than 12:00 work: Maybe by accident. If you check 06:00 it will be 0,25 as decimal and converted to 25 which is perfectly alright (well, it does not throw an exception).
Please don't forget: It is only a guess as we haven't seen all relevant information.

Its probably a problem with the culture and the decimal point.
Use this to convert the cell value with a ´.´ as decimal point:
Double.Parse(cellValue, CultureInfo.InvariantCulture);

Related

Culture dependent NumberFormat for dates in C# VSTO Excel

I'm relatively new to C# and I'm still learning a lot. I also searched stackoverflow for similar problems but got to a point where I'm stuck.
In my VSTO Excel project I'd like to output dynamic data coming from a database with a predefined number format per column also coming from the database. The user can define his own layout of the report. Everything is working just fine, I have just problems formatting the date value.
When it's about to output a date column, the format should be automatically be determined by the program instead of predefining it in the database as well. The date value gets already inserted in the Excel sheet as the decimal number it should be. Everything okay here. When I manually format it in Excel itself, it is displayed correctly.
But I want to format the date with C# like it would be formatted when I do it manually by clicking on the short date format in Excel. And it should work in every country, regardless in which language the office package was installed.
I'm working with a German installation and I expect the format to be "TT.MM.JJJJ". When formatting the column with this fixed string, it works perfectly (at least in Germany I guess).
It makes no difference if formatting it with
CurrentWorksheet.Columns[queryColumn.Position].NumberFormat = "TT.MM.JJJJ";
or
CurrentWorksheet.Columns[queryColumn.Position].NumberFormatLocal = "TT.MM.JJJJ";
Both end up in the same (correct) result. That the first line is working as well is the first thing which was unexpected for me, but that's not the main point. I tried to format it dynamically by replacing "TT.MM.JJJJ" with the following lines:
// Leads to dd.MM.yyyy
System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
// Fixed German culture still leads to dd.MM.yyyy
CultureInfo.CreateSpecificCulture("de-DE").DateTimeFormat.ShortDatePattern;
// MM/dd/yyyy - also not helpful
CultureInfo.InvariantCulture.DateTimeFormat.ShortDatePattern;
When using the first or second ShortDatePattern the date 27.08.2014 is shown as "dd.08.yyyy". Excel simply doesn't unterstand "dd" or "yyyy". I thought at least when using NumberFormat instead of NumberFormatLocal it would work, because it's the global format, but it doesn't. It feels like Microsoft has implemented the date formatting more complicated that it could be.
How would I determine the correct date pattern here?
The answer (it still is a kind of workaround) is pretty much found in another question:
How to set localized short-date format for a cell in Excel with C#?
There's just a very small difference I had to make in the method for constructing the ShortDatePattern (the Application parameter for DateFormatComponentCodes).
public static string ConstructExcelShortDatePattern()
{
var systemDateComponentCodes = new DateFormatComponentCodes();
var excelDateComponentCodes = new DateFormatComponentCodes(Globals.ThisAddIn.Application);
string systemShortDatePattern = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
string excelShortDatePattern = systemShortDatePattern.Replace(systemDateComponentCodes.Year, excelDateComponentCodes.Year).Replace(systemDateComponentCodes.Month, excelDateComponentCodes.Month).Replace(systemDateComponentCodes.Day, excelDateComponentCodes.Day);
return excelShortDatePattern;
}
Thanks to Heinzi for finding a great answer and Jordan for providing such a useful class!

C#: doing math on weird formatted dateTimes

I've got some Date-timestamps reading in from a log file, the problem is that the log file records these timestamps weirdly, for example:
"2020061515141112" is how its in the file, which represents "2020 06/15 15:14:11.12"
The issue I'm running into is that I've got loglines for start events and end events, and I need to parse out time period between them.
My question is:
in a C# application, how can I parse the strings (yyyyMMddHHmmssff) into a format that can be used by DateTime to perform a <DateTime.Subtract> between them? I'm not super familiar with Date-times and having a hard time getting Visual Studio to agree with the below:
DateTime aDT = DateTime.Parse(aLogDate,"yyyyMddHHmmssff",System.Globalization.DateTimeStyles.None);
which meets the expected format of (string,IFormatProvider,DateTimeStyle) but arguments are invalid (is it the format provider?)
EDIT: we were able to modify the format the Log prints (sort of) to retain leading zeros in their dateTimes, so this is no longer an issue, above still in question)
DateTime aDt = DateTime.ParseExact(aLogDate, "yyyyMMddHHmmssff", System.Globalization.CultureInfo.InvariantCulture);
Help from a friend came first. Heres what I wanted, people were getting to caught up on details, should have made question more concise to begin with

DateTime format - one digit day not recognized

I need to read a String in the following format: "6102015" (meaning October 6th, 2015) and turn it into DateTime objects.
I tried the following code, which did not work:
DateTime.ParseExact("6102015", "dMyyyy", CultureInfo.CurrentCulture);
But when I tested the code using the date string with an extra 0, it worked.
DateTime.ParseExact("06102015", "dMyyyy", CultureInfo.CurrentCulture); // works correctly
Is there a way to read this date format without having to add the 0?
I thank you in advance for any help.
Is there a way to read this date format without having to add the 0?
Adding a 0 is the least of your worries, IMO. That takes one line of code.
Assuming you've got a copy of the database or something you can alter, effectively, I would:
Create a field of a date/time type, or if you must use a string, do so but use an ISO-8601 format (yyyy-MM-dd)
Parse all the values which are already 8 characters
Parse all the values which are 6 characters by inserting two 0s (so abcccc becomes 0a0bcccc)
For each remaining value, of the form abcyyyy:
Try parsing it as 0abcyyyy
Try parsing it as ab0cyyyy
If only one parse worked, store that result in the new column
Now look at all the remaining rows (i.e. the ones you haven't populated with a "known good" value
You may be able to use other data (such as insertion order) to work out which is the "right" parse...
You may not - in which case you need to decide what to do

Internationalisation query in SQL SERVER and C#

I have to make an application that will be used in USA which has decimal separator as . and in
scandinavia which has decimal separator as ,
Also scandinavian countries have extra characters like ø æ å etc
I am fairly new to such type of internationlisation.
The application and the database will be same for both USA and scandinavia.
I need your help with these questions:-
What type of collation should I use in the database ?
In the front end ( C#) Is it possible that in USA I can show the numeric values displayed as 100.00 and in scandinavia to show them as 100,00 and somehow make sure that the calculations and saving to the database works without any problem?
Thank you
In SQL Server, collation is used for operations such as sorting on text data, so I don't think that decision would affect currency etc.
From .NET front-end (and sql back-end), you have to choose correct data type (such as Decimal, DateTime) for manipulating the data - for display & input purpose, you can do locale specific formatting (e.g. see currency format specifier in numeric formatting string). You can specify the format in functions such as Decimal.ToString or String.Format. These will use your current locale but you can have overrides to specify locale specific format providers. Similarly you have Parse method to convert from string to actual data type.
You can choose a collation here Selecting a SQL Server Collation there are scandinavian collations.
The decimal delimeter depends on Windows settings and will not affect your calculations.
You will have some problems with converting character expressions to a numeric data type.
Data Type Conversion:
Character expressions that are being converted to an exact numeric
data type must consist of digits, a decimal point, and an optional
plus (+) or minus (-). Leading blanks are ignored. Comma separators,
such as the thousands separator in 123,456.00, are not allowed in the
string.
Make all your string data types are NVARCHAR (or NCHAR if fixed length) so that you support unicode characters.
Since you say that your 'database' will be the same, do you mean that the server is the same physical instance, or just the same schema?
If you will have a separate server for USA to Scandinavia, this means you just set your SQL server collation and your Windows Server localization settings to USA or Scandinavia, you will need to test your solution under both environments continuously through development to ensure than any error doesn't propagate for too long unnoticed.
It's also possible to have a single database instance and then just change the localization at the WS / application side, for example this means you pass all times and numbers as USA format. But you display the values as either USA or Scandinavia format, if you're a installed (and not a web-app) you could run this control off the user's local computer localization setting which should do most of the heavy lifting for you without a problem.
eg: DateTime.Now.ToString() will report "16:34 14/11/2011" for one localization setting but "16:34 11/14/2011" for USA localization, internally the data is the same.
Lastly, if you are using a single central database, make sure you save your dates as UTC time rather than local time, otherwise you will be ignoring timezone differences between the data.

System.Convert.ToSingle() Problems, (1.5) vs (1,5)

I'm writing program in C# for converting between model formats.
The model format has numbers as text such as "-0.136222".
I can use System.Convert.ToSingle() to convert this to a floating point number. But here in Germany we use commas as decimal points (-0,136222), and System.Convert picks up on this. Now I have the problem of it not recognizing decimal points since it expects commas.
In a nutshell;
We have this: "-0.136222"
We get this: -0136222.0f
because it expects this: "-0,136222"
Can I tell system to recognize commas as decimal points just for my program? A work around won't work since it needs to be portable (to other countries).
Use Single.Parse() instead, like this:
Single.Parse("-0.136222", CultureInfo.InvariantCulture);
InvariantCulture is the way to tell the method to parse the string ignoring locale-specific decimal and grouping separators.
Leave it as it is. The .Net framework installed on your clients' computers will automatically choose the correct way to parse the data for the country settings that computer is set for. So for example, in continental Europe it will parse your float using commas, but in the USA, UK and others where we use decimal points it will parse the data using decimal points.
Of course, you can override this Culture-specific localisation feature of .Net by using CultureInfo.InvariantCulture (like Pawel has suggested) or any other CultureInfo but this will mean you have to set it specifically for each country you sell your software to. Far better to just let the framework do the work for you :)
Note: It will also mean that a (say) German person working in the USA with his PC set to be localised for Germany will have his floats parsed with commas, as he expects, not with decimal points just because he is located in the USA.

Categories