I need to parse a string and convert it to DateTime . I have the following snippet :
using (StreamReader reader = new StreamReader(fichier))
{
while ((item = reader.ReadLine()) != null)
{
string[] table = item.Split('\t');
string _date = table[2];
pointages.Add(DateTime.ParseExact(_date,"yyyy-MM-dd-hh:mm:ss", CultureInfo.InvariantCulture,DateTimeStyles.None));
}
}
Edit2
the content of the file:
917 2014-06-24-07:43:47 Finger
the string _date =2014-06-24-07:43:47. When i execute the program i got this exception:
String was not recognized as a valid DateTime.
Edit
When i added a line before like this :
while ((item = reader.ReadLine()) != null)
{
string[] table = item.Split('\t');
string _date = table[2];
_date ="2014-06-24-07:43:47";
pointages.Add(DateTime.ParseExact(_date,"yyyy-MM-dd-hh:mm:ss", CultureInfo.InvariantCulture,DateTimeStyles.None));
}
It Works!!!
What are the reasons of this error?
How can i fix it?
Your sample string works for me, so it must be a different string. Use the debugger. Maybe it is actually using 24h clock like 17:43:47, then you need HH instead of hh.
You: no, it is really the string i've posted.
That's impossible. Maybe it has leading or trailing spaces, use Trim first:
_date = _date.Trim();
Trim removes not only spaces but all kind of characters that belong to SpaceSeparator, LineSeparator or ParagraphSeparator caregories. So maybe it was a tab or whatever. Have a look at the remarks section of Char.IsWhiteSpace which is used by String.Trim.
Side-Note: if you don't know if the format is valid you could use DateTime.TryParseExact instead which doesn't raise an exception but returns false if a string could not be parsed to DateTime:
bool couldBeParsed = DateTime.TryParseExact(
_date.Trim(),
"yyyy-MM-dd-HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out dt);
Related
I have a timestamp from a server of the form 20220505 17:36:29 - it has 2 whitespaces, and I do not trust the sender to always send the same number of whitespaces in future revisions - ideally would like to handle any number of whitespaces the same.
I tried this with DateTime.ParseExact but failed:
var horribleTimestamp = "20220505 17:36:29";
var timestamp = DateTime.ParseExact(horribleTimestamp, "yyyyMMdd hh:mm:ss", CultureInfo.InvariantCulture)
// throws `System.FormatException: String '20220505 17:36:29' was not recognized as a valid DateTime.`
To save my headaches with timezones later how can I achieve this with Nodatime as i think makes sense to switch to that already.
The time is local from my PC and I would like to convert this to a global timestamp (which I believe should be Instant?) for a given local timezone?
If you want to handle any amount of whitespace, there are two options:
Use a regular expression (or similar) to get it into a canonical format with a single space
Split on spaces and then parse the first and last parts separately. (Or split on spaces, recombine the first and last parts and parse...)
In Noda Time, the value you've got represents a LocalDateTime, so that's what you should parse it to. Here's a complete example using the regex approach:
using NodaTime;
using NodaTime.Text;
using System.Text.RegularExpressions;
// Lots of spaces just to check the canonicalization
string text = "20220505 17:36:29";
// Replace multiple spaces with a single space.
string canonicalized = Regex.Replace(text, " +", " ");
// Note: patterns are immutable; you should generally store them in
// static readonly fields. Note that "uuuu" represents an absolute year number,
// whereas "yyyy" would be "year of era".
LocalDateTimePattern pattern =
LocalDateTimePattern.CreateWithInvariantCulture("uuuuMMdd HH:mm:ss");
ParseResult<LocalDateTime> result = pattern.Parse(canonicalized);
// Note: if you're happy with an exception being thrown on a parsing failure,
// juse use result.Value unconditionally. The approach below shows what to do
// if you want to handle parse failures without throwing an exception (or with
// extra behavior).
if (result.Success)
{
LocalDateTime value = result.Value;
Console.WriteLine(value);
}
else
{
// You can also access an exception with more information
Console.WriteLine("Parsing failed");
}
You can pass multiple formats to ParseExact as an array
var horribleTimestamp = "20220505 17:36:29";
var formats = new[]{"yyyyMMdd HH:mm:ss","yyyyMMdd HH:mm:ss","yyyyMMdd HH:mm:ss"};
var timestamp = DateTime.ParseExact(horribleTimestamp, formats, CultureInfo.InvariantCulture, 0);
dotnetfiddle
You have an error in your format. use HH instead of hh. See updated code below
var horribleTimestamp = "20220505 17:36:29";
var timestamp = DateTime.ParseExact(horribleTimestamp, "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture)
Here is y link that explains what you can use in a format -> https://www.c-sharpcorner.com/blogs/date-and-time-format-in-c-sharp-programming1
You can solve the problem with the whitespaces in this way:
var horribleTimestamp = "20220505 17:36:29";
var date = horribleTimestamp.Substring(0, 8);
var index = horribleTimestamp.LastIndexOf(' ') + 1;
var time = horribleTimestamp.Substring(index, horribleTimestamp.Length - index);
var timestamp = DateTime.ParseExact($"{date} {time}", "yyyyMMdd HH:mm:ss", CultureInfo.InvariantCulture);
I suppose that date has always 8 characters and that space is always present. In other case, check index == -1.
I am trying to convert a System.string to a System.double, the input is: He: 4.002602 amu
Code:
string[] data = line.Replace(" ", "").Replace("amu", "").Split(new char[] { ':' });
double i = Convert.ToDouble(data[1]);
I have tried:
string[] data = line.Replace(" ", "").Replace("amu", "").Split(new char[] { ':' });
double i = Convert.ToDouble(data[1], CultureInfo.InvariantCulture);
You can use following regular expression without splitting a string which mixed with number and words:
// using System.Text.RegularExpressions
var resultString = Regex.Match(line, #"\d.\d+").Value;
If format of input is something+blank+doubleNumber+blank+something you can use following code:
string line = "He: 4.002602 amu";
int intLspacePos = line.IndexOf(" ") + 1;
int intRspacePos = line.LastIndexOf(" ");
string strNumber = line.Substring(intLspacePos, intRspacePos - intLspacePos);
double dblNumber = Convert.ToDouble(strNumber);
Instead of Convert.ToDouble() use the double.Parse() method, preferably using the invariant culture when the user input is always using a period sign as decimal separator.
So try something like this:
double i = double.Parse(data[1], CultureInfo.InvariantCulture);
EDIT:
I've seen in the screenshot you posted in the comments above that you're not actually checking the contents of data[1] before passing it to the Convert.ToDouble method.
According to MSDN the only case when a FormatException is thrown should be when providing a non-numeric text value (see here). Therefor I'd suggest to add a check for empty strings and null values before, passing the value to the Convert.ToDouble() method. Try updating your code to something like this:
foreach (string line in raw) {
string[] data = line.Replace(" ", "").Replace("amu", "").Split(new char[] { ':' });
if (!string.IsNullOrWhiteSpace(data[1]) {
double i = Convert.ToDouble(data[1], CultureInfo.InvariantCulture);
} else {
// Invalid value in data[1]
// Maybe set a breakpoint here and investigate further if necessary
}
}
If this still throws a FormatException then the contents of data[1] must be some non-numeric and non-empty text value, so in that case you should probably check the contents of the data array using the debugger and find out how / why that invalid value got there.
you can convert with specific culture info as below. 2057 is LCID for English (UK).
double i = Convert.ToDouble(data[1], CultureInfo.GetCultureInfo(2057));
I have the following code:
string[] format = { "yyyy/MM/dd", "MM/dd/yyyy" };
DateTime valueDate;
value = value.Replace("-", "/");
if (DateTime.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out valueDate))
{
value = "TO_DATE(" + valueDate + ", 'yyyy-mm-dd')";
}
else
{
throw new Exception("Could not parse incoming date: " + valueDate);
}
So now I have a test case.
And value = '2013/01/21' after the replace statement replacing "-" with "/".
This should match the first format in the format string array.
But TryParseExact is not working and always goes to the else path.
Can anyone see any errors in this code?
It's not TryParseExact that's the problem, it's the value of your string. I say that because this little scriptcs script:
using System.Globalization;
string[] format = { "yyyy/MM/dd", "MM/dd/yyyy" };
DateTime valueDate;
var value = "2013/01/21";
if (DateTime.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out valueDate))
{
Console.WriteLine("Success!");
}
else
{
Console.WriteLine("Failure!");
}
prints Success!. So, in other words, this statement:
And value = '2013/01/21' after the replace statement replacing "-" with "/".
literally cannot be correct.
As stated by James, it's very possible there is whitespace in the actual string value. There are a couple solutions: remove the whitespace or allow whitespace. To allow whitespace you could use DateTimeStyles.AllowWhiteSpaces rather than DateTimeStyles.None.
Don't know if it's your issue, but make sure you always escape out your forward-slashes when using date formats. A / character is not a literal slash, but rather your local system's date separator (which is usually the forward-slash, but not always).
When using a format string, you escape a forward-slash with a real backslash, like:
DateTime.ParseExact("2012/12/31", "yyyy\\/MM\\/dd", null);
// or
DateTime.ParseExact("2012/12/31", #"yyyy\/MM\/dd", null);
Just curious...
So I get that if I convert the string version of the date to a DateTime object and pass it into the String.Format() method, then I"ll get the desired results.
String.Format("The date is {0:MMMM dd, yyyy}", DateTime.Parse("05-22-2012"));
"The date is May 22, 2012"
But why doesn't this work?
String.Format("The date is {0:MMMM dd, yyyy}", "05-22-2012")
"The date is 05-22-2012"
Sorry if this is a stupid question, but I'm just trying to understand how this works.
Thanks
The other answers here hit on salient points, but let's put them all together an examine how String.Format works.
It has five overloads, but we're going to talk only about the one that they all redirect to (this is not the actual code, if you want to see it with Reflector or ILSpy, you will find it in StringBuilder.AppendFormat). This is simplified for easy understanding.
public static string Format(IFormatProvider provider, string format, params object[] args)
{
StringBuilder sb = new StringBuilder();
// Break up the format string into an array of tokens
Token[] tokens = ParseFormatString(format);
foreach (Token token in tokens)
{
switch (token.TokenType)
{
// A Text token is just some text to output directly
case TokenType.Text:
sb.Append(token.Text);
break;
// An Index token represents something like {0} or {2:format}
// token.Index is the argument index
// token.FormatText is the format string inside ('' in the first example, 'format' in the second example)
case TokenType.Index:
{
object arg = args[token.Index];
IFormattable formattable = arg as IFormattable;
if (formattable != null && token.FormatText.Length > 0)
{
// If the argument is IFormattable we pass it the format string specified with the index
sb.Append(formattable.ToString(token.FormatText, provider));
}
else
{
// Otherwise we just use Object.ToString
sb.Append(arg.ToString());
}
}
break;
}
}
return sb.ToString();
}
In your question you ask why the format string doesn't get applied when you pass "05-22-2012". As Guffa said, that is not a DateTime object, it is a String object.
As GSerjo said, a String is not IFormattable. Strings are not formattable because formatting is the process of converting something into a String. A string is already a string!
So you can see that when the Format method gets to indexer, arg will not be IFormattable and it will simply call ToString. Calling ToString on a string simply returns itself, it's already a string.
In summary, if your format string contains an index with an inner-format string (e.g. {0:format}), that inner-format string will only be applied if the associated argument is IFormattable and it knows what to do with the format string you give it.
A custom datetime format only works on a DateTime value. If you are using a string instead, the format will be ignored because there is only one way to output a string.
Because "05-22-2012" is not IFormattable, DateTime.Parse("05-22-2012") it's DateTime
please look here for more examples
String Format for DateTime
Custom Date and Time Format Strings
I have a string like 20090101 and I want to compare it with ????01??.
if (input == "----01--") { .... }
How can I compare the 5th and 6th characters with "01"?
Update: After seeing your comment I think you should parse the string as a DateTime:
string s = "20090101";
DateTime dateTime;
if (DateTime.TryParseExact(s, "yyyyMMdd", null, DateTimeStyles.None, out dateTime))
{
if (dateTime.Month == 1)
{
// OK.
}
}
else
{
// Error: Not a valid date.
}
I think this may be what you want:
if (input.Substring(4, 2) == "01")
{
// do something
}
This will get a two character substring of input (starting at character 5) and compare it to "01".
you should create a regex expression. to check if the 4th and 5th byte is 01, you can write
var r = new Regex("^.{4}01$");
if(r.Match(str) ...) ...
MSDN has a great article on comparing strings, but you may want to refer to the String documentation for specific help, most notably: String.Compare, String.CompareTo, String.IndexOf, and String.Substring.
As Bauer said you can use String functions, also you can convert string to Char Array and work with it char by char