Get DateTime from FileName - c#

I have a file named test-2000_01_02-10_12_14.xml.
How do I only get the date from the file?
I was able to get the date if the file has this name: 2000_01_02-10_12_14
with this (b is a StorageFile):
DateTime dateVal;
bool parsed = DateTime.TryParseExact(b.DisplayName,
"yyyy_MM_dd-H_mm_ss",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out dateVal);
I then tried to change yyyy_MM_dd-H_mm_ss to something like this *-yyyy_MM-dd-H-mm_ss but it does not seem to be the solution

There are a boatload of ways to do this, it really rather depends on how regular the naming of your files is - is there always some junk text followed by a hyped, then the year?
Post up another 10 different examples if you want more tailored advice. Here's a way for the one you've posted:
DateTime.TryParseExact(
Path.GetFileNameWithoutExtension(b.DisplayName.Substring(b.DisplayName.IndexOf('-')+1)),
"yyyy_MM_dd-H_mm_ss",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out dateVal
);
This uses Substring with only one argument (no length) to remove everything after the first hyphen up to the end of the string, and GetFileNameWithoutExtension to remove the .xml - this effectively turns anythinghere-2000_01_01-00_00_00.xml into 2000_01_01-00_00_00 ready for parsing
I could also have gone for a .Remove("last index of period") type thing but it does get a bit messy because you have to subtract the start Index of the hyphen etc
MJWill's comment about splitting on hyphen is also a good one - you could split then take the [1] and [2] indexes and join then back together for parsing..
Lastly don't forget that the file itself might have a created date that is already a good candidate for the date of creation rather than the filename (which might be mangled by humans) so long as it hasn't been transmitted somewhere and re-saved. Take a look at the FileInfo.CreationTime property for that - https://learn.microsoft.com/en-us/dotnet/api/system.io.fileinfo?view=netframework-4.8

First, we have to extract (match) the datetime part from a file name:
using System.Text.RegularExpressions;
...
// Aggravated task: dots and minuses within file's name
string source = #"bla-bla-bla-test.me-2000_01_02-10_12_14.xml";
string datetime = Regex.Match(
Path.GetFileNameWithoutExtension(source),
"[0-9]{4}_[0-9]{2}_[0-9]{2}-[0-9]{2}_[0-9]{2}_[0-9]{2}$").Value;
Then we can parse it
if (DateTime.TryParseExact(
datetime,
"yyyy_MM_dd-H_m_s",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out DateTime result) {
// result is the parsed date
}
else {
// File doesn't contain valid date and time
}

I would suggest you to use regular expression assuming that your file name will be always following the same format you can do something like this:
var pattern = #"\d{4}_\d{2}_\d{2}-\d{2}_\d{2}_\d{2}";
var fileName = "test-2000_01_02-10_12_14.xml";
var match = new Regex(pattern);
var result = match.Match(fileName);
if (result.Success)
{
DateTime.TryParseExact(result.Value,
"yyyy_MM_dd-HH_mm_ss",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None,
out DateTime dateVal);
}

Related

What does the 0 in "{0:MM dd yyyy}" do?

I'm new to the C#/MVC world. I spend a lot of time today figuring out how to display a DateTimeOffset object in the format i want. Finally got it working this way.
Html.TextBoxFor(model => model.DeliveryDate,"{0:MM/dd/yyyy}",
new { htmlAttributes = new { #class = "datepicker" } })
But I still don't understand the importance of '0' in the format string. the page breaks if i replace the 0 with any other number or totally remove it. Can someone help me understand this?
From String.Format Method
The {0} in the format string is a format item. 0 is the index of the object whose string value will be inserted at that position. (Indexes start at 0.) If the object to be inserted is not a string, its ToString method is called to convert it to one before inserting it in the result string.
That's a format string with parameters (like used in e.g. Console.WriteLine, or string.Format). The {0} would be the placeholder for the first argument, and {0:mm/dd/yyyy} is simply a format string to convert the first argument to a string.
When you use the string.Format you can pass the space for arguments like {0}, {1}, etc which is the indexes you pass as arguments for the method. It is the same for asp.net razor helpers.
You also can provide the format after the index separating by :, for sample: {0:0.00} as format for a number with 2 decimals places or {1:dd/MM/yyyy} for dates etc.
String Interpolation
There is a new way to implement it using the String Interpolation. Basically, you can concat the values on your string without generating new strings. For sample:
var i = 18;
var s = $"You are {age} years old.";
Since you start the string with $, you can pass arguments between { and }. You also can use the same formats to format your data as you use on string.Format. For sample:
var today = $"Today is {DateTime.Now:D}";
var date = DateTime.Now.Add(1);
var tommorrow = $"Tommorrow is {date:dd/MM/yyyy}";
See the documentation for String.Format():
https://msdn.microsoft.com/en-us/library/system.string.format.aspx
In a nutshell, when the model is rendered to HTML text, the DeliveryDate object value will be passed to String.Format(), where {0} indicates the index of the first value in an array of values being passed to Format(). So {0:MM/dd/yyyy} just means to format the first value in the array using date components. Basically, it will do something like this internally:
String s = SomeValueArray[0].ToString("MM/dd/yyyy");
0 is a placeholder for your argument / property (in this case) DeliveryDate.. Similar to String.Format examples... so when your View is rendered.. the 0 will be replaced with whatever value that DeliveryDate is holding in the format MM/dd/yyyy

How to make DateTime.TryParse() fail if no year is specified?

Consider the following code to parse a date. (Note that I'm in the EN-gb locale):
const DateTimeStyles DATE_TIME_STYLES = DateTimeStyles.NoCurrentDateDefault | DateTimeStyles.AllowWhiteSpaces;
DateTime dt;
// Current culture for this example is "EN-gb".
if (DateTime.TryParse("31/12", CultureInfo.CurrentUICulture, DATE_TIME_STYLES, out dt))
Console.WriteLine("Parsed correctly"); // Do not want!
else
Console.WriteLine("Did not parse correctly.");
I'm deliberately omitting the year. However, TryParse() will parse this without any errors, and will substitute the current year.
I'd like to be able to force the user to enter ALL the components of the date (using their local format), so I'd like the above parsing to fail - or to be able to detect that the user didn't enter a year.
I don't really want to use DateTime.TryParseExact() because then I would have to add code to specify all the different valid formats for all the different supported locales, which is non-trivial and likely error-prone. I suspect this may well be my only sane option, though.
Anyone got any ideas? (Someone here at work has already implemented a "solution" which involves not allowing the current year, which is clearly not a good solution...)
You could query for the culture's patterns, filter out those without a year and then use TryParseExact on the remaining patterns.
var allPatterns = culture.DateTimeFormat.GetAllDateTimePatterns();
var patternsWithYear = allPatterns.Where(s => s.Contains("y")).ToArray();
bool success = TryParseExact(input, patternsWithYear, culture, styles, out dateTime);
Known bug: This doesn't take escaping into account, you'll need to replace the Contains("y") call with proper parsing to fix this.
Alternatively you could go with just LongDatePattern and ShortDatePattern if you're fine with stricter format constraints.
You can use parse exact like this and catch the exception.
CurrentUICulture.DateTimeFormat.ShortDatePattern will give you the cultures short date pattern.
There is also DateTime.TryParseExact
DateTime.ParseExact(value.ToString(), cultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern.ToString, cultureInfo.CurrentUICulture)
The more I think about this the more I think it's a bad solution but given you're getting no other answers I'll post it anyway.
DateTime temp;
DateTime.TryParse(input, CultureInfo.CurrentUICulture, DATE_TIME_STYLES, out temp);
if (temp.Year == DateTime.Now.Year)
{
if (!input.Contains(DateTime.Now.Year))
{
if (temp.Days != int.Parse(DateTime.Now.Year.ToString().SubString(2)))
{
// my god that's gross but it tells you if the day is equal to the last two
// digits of the current year, if that's the case make sure that value occurs
// twice, if it doesn't then we know that no year was specified
}
}
}
Also, as others have suggested in comments now, checking the number of tokens or the strings length could also be useful like;
char[] delims = new char[] { '/', '\', '-', ' '); //are there really any others?
bool yearFound = false;
foreach (char delim in delims)
{
if (input.Split(delim).Count == 3)
{
yearFound = true;
break;
}
}
if (yearFound)
//parse
else
// error
These are just a couple of ideas, neither is truly sound. They're obviously both hacks, only you can know if they'll suffice. At least they beat your co-workers if (dt.Year == 2014) //discard input "solution".

C# - How to format datetime to remove trailing zeros

I'm setting up an orchestration class that handles multiple actions as one big transaction. For each of these transactions I give them the same time-stamp instantiated at the beginning of the orchestration.
I user the following line:
var transactionTimestamp = DateTime.UtcNow.ToString("o");
I have a constraint in the system that dictates that the time stamp cannot have any trailing zeros.
For example:
2013-06-26T19:51:38.0083980Z //bad
2013-06-26T19:51:38.008398Z //good
2013-06-26T19:51:38.0083988Z //good
The built-in DateTime format "o" is comparable to the custom format of: "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK". If you just use that format, but replace the lower-case f's with upper case ones, there will be no trailing zeros.
ie
DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFFK");
Custom date and time format strings
You can achieve this fairly easily using Regex. Here's one way.
string result = Regex.Replace("2013-06-26T19:51:38.0083980Z", "0+Z$", "Z");
// result == "2013-06-26T19:51:38.008398Z"
string result2 = Regex.Replace("2013-06-26T19:51:38.0083988Z", "0+Z$", "Z")
// result2 == "2013-06-26T19:51:38.0083988Z"
I would write my own help method like;
public string GetDtString(DateTime dt)
{
RegEx rgx = new RegEx("[1-9]0+Z\b");
return rgx.Replace(dt.ToString("o"), System.String.Empty);
}
It basically just returns the dt string with all 0's which occur after a digit 1-9 and before Z\b (Z followed by a word boundary) with an empty string.

parsing a string into int/long using custom format strings

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.

spliting the 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.

Categories