In my C# Data Access Layer...I am retrieving a dataset from Excel ...and there is a decimal excel field which returns date in the format : 20090701. I need this to be converted to C# DateTime. What is the best way to do it?
DateTime.ParseExact( value.ToString(), "yyyymmdd" );
The ParseExact method allows you to specify the format string for the date/time you are converting. In your case: a four digit year, then two digit month, then two digit day of month.
I would do something like this if you want to implement it application wide.
System.Globalization.CultureInfo cultureInfo =
new System.Globalization.CultureInfo("en-CA");
// Defining various date and time formats.
dateTimeInfo.LongDatePattern = "yyyyMMdd";
dateTimeInfo.ShortDatePattern = "yyyyMMdd";
dateTimeInfo.FullDateTimePattern = "yyyyMMdd";
// Setting application wide date time format.
cultureInfo.DateTimeFormat = dateTimeInfo;
// Assigning our custom Culture to the application.
//Application.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
DateTime.Parse(excelDate);
And a less intuitive answer for good measure.
var a = 20090701m;
var b = a / 10000;
var year = (int)b;
var c = (b - year) * 100;
var month = (int)c;
var day = (int)((c - month) * 100);
var dt = new DateTime(year, month, day);
Related
I trying to parse a string like 4212021 where 4 is the month, 21 is the day, and 2021 is the year, into a DateTime object. I've tried using the following code but for some reason I am getting 'String '4212021' was not recognized as a valid DateTime.':
string datetimestring = "4122021";
var date = DateTime.ParseExact(datetimestring, "Mddyyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
All help is appreciated. Thanks.
This doesn't work without date separators. So you could add them:
string format = "Mddyyyy";
CultureInfo culture = CultureInfo.InvariantCulture;
string separator = culture.DateTimeFormat.DateSeparator;
if(datetimestring.Length >= format.Length)
{
int firstIndex = datetimestring.Length % 2 == 0 ? 2 : 1;
datetimestring = datetimestring.Insert(firstIndex, separator);
datetimestring = datetimestring.Insert(firstIndex + 2 + separator.Length, separator);
}
DateTime date = DateTime.Parse(datetimestring, culture, DateTimeStyles.None);
This works also if the month has two digits like in "12122021".
Another, maybe simpler way was to use ParseExact with "Mddyyyy HHmmss" and append zero time:
datetimestring = datetimestring + " 000000"; // check first length ofc
DateTime date = DateTime.ParseExact(datetimestring, "Mddyyyy HHmmss", culture, DateTimeStyles.None);
It's just the "M" modificator that does not work if you use it without separators AND with variable length. If you ensure leading zeros, it should work. ("04" instead of "4")
string datetimestring = 4122021.ToString("D8");
var date = DateTime.ParseExact(datetimestring, "Mddyyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
Since your day is always 2 digits (dd) you can just append a 0 to the start of the string when the month only has 1 digit, and use the MM for month:
string datetimestring = "4122021";
var date = DateTime.ParseExact(datetimestring.PadLeft(8,'0'), "MMddyyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
I am imagining you have a special reason for not changing the input. You can try this way, it will work.
string datetimestring = "4122021";
var date = DateTime.ParseExact(datetimestring.Length < 8 ? $"0{datetimestring}" : datetimestring, "Mddyyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
See if it is appropriate for your context?
In database I have a string that represent a date time that format is YY.MM (YY it means Year and MM is Month. for example 21.03 = 2021.03)
How can I map this special format(yy.mm) to this format(mm/yyyy) by using data annotation or another way ?
Try Parse date and then format back to the string:
using System.Globalization;
...
string source = "21.03";
// 03.2021
string result = DateTime
.ParseExact(source, "yy'.'MM", CultureInfo.InvariantCulture)
.ToString("MM'.'yyyy");
However, we have an ambiguity here: "03.50" can be either "March 1950" or "March 2050". The default policy is 00..29 to 2000..2029 and 30..99 to 1930..1999 if you want to change this policy you can create and use your own culture:
CultureInfo myCulture = CultureInfo.InvariantCulture.Clone() as CultureInfo;
// Everything to 20.., never 19..
myCulture.Calendar.TwoDigitYearMax = 2099;
string source = "99.03";
// 03.2099
string result = DateTime.ParseExact(source, "yy'.'MM", myCulture).ToString("MM'.'yyyy");
Or even
CultureInfo myCulture = CultureInfo.CurrentCulture.Clone() as CultureInfo;
// Everything to 20.., never 19..
myCulture.Calendar.TwoDigitYearMax = 2099;
// Current culture as usual, except 2 digit year policy
CultureInfo.CurrentCulture = myCulture;
...
string source = "99.03";
// 03.2099
string result = DateTime.ParseExact(source, "yy'.'MM", null).ToString("MM'.'yyyy");
You can do it like this using the string split function:
string dateIn = "11.10";
string month = dateIn.Split('.')[1]; //split the String at the point and save it
string year = dateIn.Split('.')[0];
string dateOut = $"{month}/20{year}"; //build a new string
//this will fix the 1900/2000 issue more or less as all dates in the furutre would be send back to the past you can adapt this to your need:
if( DateTime.Now.Year < Convert.ToInt32($"20{year}"))
{
dateOut = $"{month}/19{year}";
}
//dateOut is "10/2011"
How do I convert this string into a date time with milliseconds
03/04/2019 15:16:57.73
The format is day/month/year hour:minutes:seconds.milliseconds.
I tried it like this:
var format = "dd/MM/yyyy HH:mm:ss.fff";
var year = dateTime.Substring(0, 4);
var month = dateTime.Substring(4, 2);
var day = dateTime.Substring(6,2);
var hour = dateTime.Substring(8, 2);
var minute = dateTime.Substring(10, 2);
var seconds = dateTime.Substring(12, 2);
var miiliseconds = dateTime.Substring(14, 2);
var stringDate = $#"{day}/{month}/{year} {hour}:{minute}:{seconds}.{miiliseconds}";
var transactioDateTime = DateTime.ParseExact(stringDate, format, CultureInfo.InvariantCulture);
But I get an error of
Additional information: String was not recognized as a valid DateTime.
Can you please help me with this? Thank you.
Seems like you don't need substrings at all.
Just put your date string right into ParseExact and you will get what you want.
However the error there is because you have different milliseconds format: it expects you will put three digits there but you passed only two:
var dateTime = "03/04/2019 15:16:57.73";
var format = "dd/MM/yyyy HH:mm:ss.ff"; - this is the fix.
I am trying to read an Excel file in my ASP.NET application using the following piece of code (ADO.NET):
// Create OleDbCommand object and select data from worksheet Sheet1
String query = String.Format("Select * From [{0}$]", sheetName);
OleDbCommand cmd = new OleDbCommand(query, oledbConn);
// Create new OleDbDataAdapter
OleDbDataAdapter oleda = new OleDbDataAdapter();
oleda.SelectCommand = cmd;
//Fills Data to DataTable
oleda.Fill(dt);
The problem is that values in the data table are represented
1) For decimals either with a comma (3,14) or with a dot (3.14)
2) For dates with either the format 'DD/MM/YYYY' or'MM/DD/YYYY'
For the same Excel file depending on the locale settings server has.
Is there any way to read the data in a specific locale in order to get the correct values from the Excel file?
In the case of the column with decimals, use the following to parse them: (Decimal.Parse)
string decimal1 = "3,14";
string decimal2 = "3.14";
decimal d1 = decimal.Parse(decimal1, new NumberFormatInfo { NumberDecimalSeparator = "," });
decimal d2 = decimal.Parse(decimal2);
Note that with a , you need to use a custom NumberFormatInfo for it to parse right.
Then for your DateTime column:
string date1 = "14/03/2018";
string date2 = "03/14/2018";
DateTime dt1 = DateTime.ParseExact(date1, "dd/MM/yyyy", CultureInfo.InvariantCulture);
DateTime dt2 = DateTime.ParseExact(date2, "MM/dd/yyyy", CultureInfo.InvariantCulture);
Here you will want to specify the differnt formats for your dates.
EDIT:
To be more general about parsing an unknown DateTime format, you could try iterating through all the formats for your CultureInfo or multiple CultureInfo if you know there might be more than one. An example is below of how you could do this:
string dateTimeString = #"03/14/2018";
string[] possibleStandardFormats = new CultureInfo("en-US")
.DateTimeFormat.GetAllDateTimePatterns();
DateTime? result = null;
foreach (string format in possibleStandardFormats) {
if (DateTime.TryParse(dateTimeString, out DateTime dateTime)) {
// this format could work
result = dateTime;
break;
}
}
if (result == null) {
// no luck with any format
// try one last parse
if (DateTime.TryParse(dateTimeString, out DateTime dateTime)) {
// finally worked
result = dateTime;
}
else {
// no luck
}
}
Here it may be more effective to try the general DateTime.TryParse first (shown at the end of this example), as it could save you the iterations through the other formats. Up to you how you want to handle this, but this example should handle the majority of the cases.
EDIT 2:
In order to get the standard DateTime formats, you can use the CurrentCulture which will help with your dates. In my previous edit, I hard coded new CultureInfo("en-US"), but the below is a bit more general.
string[] possibleStandardFormats = new CultureInfo(CultureInfo.CurrentCulture.Name)
.DateTimeFormat.GetAllDateTimePatterns();
EDIT 3:
To expound a bit more on the previous parsing of decimals, first check if the string has a comma and then parse it according to the method I have listed above.
string decimal1 = "3,14";
if (decimal1.Contains(",")) {
decimal d1 = decimal.Parse(decimal1, new NumberFormatInfo { NumberDecimalSeparator = "," });
}
else {
decimal d1 = decimal.Parse(decimal1);
}
EDIT 4:
To incorporate culture into parsing decimals, you can try the Convert.ToDecimal method. One of its parameters takes a CultureInfo where you can pass in your current culture as CultureInfo.CurrentCulture. For example below, I am using de-de (German) since that is a valid culture for 1.234,14
string decimal1 = "1.234,14";
string decimal2 = "1,234.14";
decimal d1 = Convert.ToDecimal(decimal1, new CultureInfo("de-de"));
decimal d2 = Convert.ToDecimal(decimal2, CultureInfo.CurrentCulture);
Current culture of my application is set to Spanish but i need to convert my date to English in order to perform database operations.
currently date is coming in this format: "Dic 13, 2017"
I need to convert this to : "Dec 13, 2017"
what i have tried until now
var input = objDMSampleA.RequestDateFrom;
var format = "MMM dd, yyyy";
var dt = DateTime.ParseExact(input, format, new CultureInfo("es-ES"));
var result = dt.ToString(format, new CultureInfo("en-US"));
but the ParseExact gives error that
String was not recognized as a valid DateTime.
"Short" month names for given culture are stored in CultureInfo.DateTimeFormat.AbbreviatedMonthNames. For es-ES culture those names might have dot in the end (for example: "dic." instead of "dic"). For that reason, parsing your string fails - "Dic" doesn't have that dot.
To fix this, one way is to modify those names:
var esCulture = new CultureInfo("es-ES");
var monthNames = esCulture.DateTimeFormat.AbbreviatedMonthNames;
for (int i = 0; i < monthNames.Length; i++) {
monthNames[i] = monthNames[i].TrimEnd('.');
}
esCulture.DateTimeFormat.AbbreviatedMonthNames = monthNames;
monthNames = esCulture.DateTimeFormat.AbbreviatedMonthGenitiveNames;
for (int i = 0; i < monthNames.Length; i++)
{
monthNames[i] = monthNames[i].TrimEnd('.');
}
esCulture.DateTimeFormat.AbbreviatedMonthGenitiveNames = monthNames;
Then your code will work as expected:
var input = "Dic 13, 2017";
var format = "MMM dd, yyyy";
var dt = DateTime.ParseExact(input, format, esCulture);
var result = dt.ToString(format, new CultureInfo("en-US"));
It's better to store modified culture in some static field and reuse it, instead of creating it and changing every time.
If you want to modify current culture for all threads, use
CultureInfo.DefaultThreadCurrentCulture = esCulture;
though I won't recommend doing that.