I've simplified my code down to this:
string when = "03/03/15 12:00 18:00";
string difference = Convert.ToString(Convert.ToDateTime(when.Substring(when.Length - 5, 5)) - Convert.ToDateTime(when.Substring(when.Length - 10, 10))).substring(difference.Length - 5, 5);
But it's still very complex and also doesn't work :/
Basically I want the string difference to equal 6 because 18 - 12 is 6. It needs to be a little bit more complex because I want to evolve minutes too.
Am I being an idiot? Is it easy?
Just convert your string to a couple of valid DateTime values, and subtract them.
The Hours property will give you a representation of the difference in whole hours, in this case 6.
string when = "03/03/15 12:00 18:00";
string[] portions = when.Split(); // 3 items: "03/03/15", "12:00", "18:00"
string yourDateTimeFormat = "MM/dd/yyHH:mm"; // or "dd/MM/yyHH:mm" if the day is first
// create a valid date from 03/03/15 and 12:00
DateTime fromTime = DateTime.ParseExact(
portions[0] + portions[1], yourDateTimeFormat, CultureInfo.CurrentCulture, DateTimeStyles.None);
// create a valid date from 03/03/15 and 18:00
DateTime toTime = DateTime.ParseExact(
portions[0] + portions[2], yourDateTimeFormat, CultureInfo.CurrentCulture, DateTimeStyles.None);
int differenceInHours = (toTime - fromTime).Hours;
Depending on how much control you have over the input, you may want to add additional logic for checking that the date is valid, or consider using DateTime.TryParseExact instead.
Related
I receive a string in this format "7:00 am - 11:00 pm" representing start and end time. The string will always have two times. Now I need to format that to today's date & time so in above case it's easy. It comes to 18th March 7 AM - 18th March 11 PM but there is an edge case where time is like "7:00 am - 12:00 am", in this case it will need to be converted to 18th March 7 AM - 19th March 12 AM.
Now I can handle this using if :D. So whenever the second token is smaller than first token (e.g. "7:00 am - 02:00 am") I can increase the date of the second part.
string input = "7:00 am - 12:00 am";
List<DateTime> tokens = input.Split('-').Select(x => DateTime.Parse(x.Trim(), CultureInfo.GetCultureInfo("en-NZ"))).ToList();
if(tokens[1] < tokens[0]){
tokens[1] = tokens[1].AddDays(1);
}
But I would like to know if there is any builtin way in C# itself through Timespan, Datetime classes etc to handle it.
The code is okay for the requirements you have listed, you could consider hiding some of the logic away by creating an extension method and using DateTime.Hour in your if statement:
public static class StringExtensions
{
public static IEnumerable<DateTime> ToDateTimePairs(this string input)
{
var dates = input.Split('-').Select(x => DateTime.Parse(x.Trim(), CultureInfo.GetCultureInfo("en-NZ"))).ToList();
if (dates[1].Hour < dates[0].Hour)
{
dates[1] = dates[1].AddDays(1);
}
return dates;
}
}
Your code then becomes:
string input = "7:00 am - 12:00 am";
var dates = input.ToDateTimePairs();
foreach(var date in dates)
{
Console.WriteLine(date);
}
Console.ReadKey();
Aside: You could also add some validation steps in ToDateTimePairs() (you should only have two valid DateTime objects after splitting the string, etc). The way you implement it is up to you; right now, if an invalid date is contained in the string, the call to DateTime.Parse() will throw a FormatException - if you'd like to handle the validation of the parsing yourself, consider using DateTime.TryParse() instead.
If I have a string like 15:00 and I parse this to DateTime ot DateTimeOffset, the date is set to today.
I want somehow to distinguish, if the date part is given or not. It would help, if the date part is not given, the date is 1.1.1970.
Is there a better possibility instead of using regex and parse this by my own?
Try to parse the value as TimeSpan and then try to parse it as DateTime.
var data = "15:00";
if (TimeSpan.TryParse(data, out var time))
{
Console.WriteLine("Time: {0}", time);
}
else if (DateTime.TryParse(data, out var datetime))
{
Console.WriteLine("DateTime: {0}", datetime);
}
else
{
Console.WriteLine("I don't know how to parse {0}", data);
}
If I have a string like "15:00" and I parse this to DateTime ot
DateTimeOffset, the date is set to today.
This is by design.
From DateTime.Parse doc:
A string with a time but no date component. The method assumes the
current date unless you call the Parse(String, IFormatProvider,
DateTimeStyles) overload and include
DateTimeStyles.NoCurrentDateDefault in the styles argument, in which
case the method assumes a date of January 1, 0001.
From DateTimeOffset.Parse doc:
If is missing, its default value is the current day.
So, for DateTime, if you don't use any DateTimeStyles, you get the current date
var hours = "15:00";
var date = DateTime.Parse(hours, CultureInfo.InvariantCulture); // 12/9/2018 3:00:00 PM
but if you use DateTimeStyles.NoCurrentDateDefault as a third parameter;
var hours = "15:00";
var date = DateTime.Parse(hours, CultureInfo.InvariantCulture, DateTimeStyles.NoCurrentDateDefault);
// 1/1/0001 3:00:00 PM
But I think your problem keeps on that sentence; "if the date part is given or not.." How did you decide your string has date part or not? Is it always have 5 characters as Steve commented? It can be in a format like 4:00? What about 4:1? If it can be like 4:1, it should be parsed as 4:10 or 4:01?
So, you need to decide first what is the meaning of "if the date part is given or not.." for your case. Then you can easily parse your string to TimeSpan, not DateTime in my opinion, so, you can add it created manually "1.1.1970" with DateTime(int, int, int) constructor.
if(YourConditionForYourStringNotIncludingDatePart)
{
var time = TimeSpan.Parse("15:00");
var date = new DateTime(1970, 1, 1);
var result = date.Add(time);
}
Using regular expressins for DateTime parsing is usually a bad idea. I wouldn't suggest to use it unless you have no other way to do it for DateTime.
I think for that case you could things keep simple. This could be a solution that not depends on the lenght when there is only a timepart:
void Main()
{
Console.WriteLine(ParseWithDummyIfDateAbsent("15:00", new DateTime(1970, 1, 1)));
Console.WriteLine(ParseWithDummyIfDateAbsent("15:00:22", new DateTime(1970, 1, 1)));
Console.WriteLine(ParseWithDummyIfDateAbsent("09.12.2018 15:00", new DateTime(1970, 1, 1)));
}
DateTime ParseWithDummyIfDateAbsent(string input, DateTime dummyDate)
{
if(TimeSpan.TryParse(input, out var timeSpan))
input = $"{dummyDate.Date.ToShortDateString()} {input}";
return DateTime.Parse(input);
}
Output:
01.01.1970 15:00:00
01.01.1970 15:00:22
09.12.2018 15:00:00
Depends on your localization:-)
I have this code that shows some build info in an About box:
private void frmAbout_Load(object sender, EventArgs e)
{
Version versionInfo =
Assembly.GetExecutingAssembly().GetName().Version;
lblVersion.Text = String.Format("Version {0}.{1}",
versionInfo.Major.ToString(), versionInfo.Minor.ToString());
String versionStr = String.Format("{0}.{1}.{2}.{3}",
versionInfo.Major.ToString(), versionInfo.Minor.ToString(),
versionInfo.Build.ToString(), versionInfo.Revision.ToString());
lblBuild.Text = String.Format("Build {0}", versionStr);
DateTime startDate = new DateTime(2000, 1, 1); // The date from
whence the Build number is incremented (each day, not each
build; see http://stackoverflow.com/questions/27557023/how-can-
i-get-the-build-number-of-a-visual-studio-project-to-increment)
int diffDays = versionInfo.Build;
DateTime computedDate = startDate.AddDays(diffDays);
lblLastBuilt.Text += computedDate.ToLongDateString();
}
It appears like this today:
The "problem" is that screen real estate is limited, and dates such as "February 04, 2015" look geekish to me (I prefer "February 4, 2015").
I could kludgily brute-force the string returned from ToLongDateString() like so:
String lds = computedDate.ToLongDateString();
lds = // find leading 0 in date and strip it out or replace it with an empty string
lblLastBuilt += lds;
(I'm using "+=" because lblLastBuilt is set to "Last built " at design-time.
So: is there a less brute-forcish way to prevent leading 0s from appearing in the "day of month" portion of the date string?
Use a custom format. (MMMM d, yyyy)
String lds = computedDate.ToString("MMMM d, yyyy", CultureInfo.InvariantCulture);
single d would give you a single or double digit day part. If the day part is below 10, then you will get only a single digit instead of leading 0, for others you will get both digits.
See: Custom Date and Time Format Strings
I prefer "February 4, 2015"
EDIT: I missed the part for day of week, I am not sure whether you need that or not but if you have to then you can add dddd in the custom format like:
dddd, MMMM d, yyyy
Try this:
computedDate.ToString("dddd, MMMM d, yyyy");
It outputs, e.g. "Wednesday, February 4, 2015" using a custom date format.
Currently it is evening and couldn't actually test it with morning hours like 7 in the morning.
but a code like this:
DateTime dt = DateTime.Now;
string str = dt.ToString("HH:mm");
So my question is can I be sure that it is always returning time in format like "07:35" and not "7:35" ?
DateTime.Now returns time without formatting. Format applied in the ToString("HH:mm") method. And yes, this format is 24-hour.
Yes because the documentation says:
The "HH" Custom Format Specifier: The "HH" custom format specifier (plus any number of additional "H" specifiers) represents the hour as a number from 00 through 23; that is, the hour is represented by a zero-based 24-hour clock that counts the hours since midnight. A single-digit hour is formatted with a leading zero.
You could test with
DateTime dt = DateTime.Now;
string str = dt.ToString("HH:mm");
Console.WriteLine(str);
DateTime t = new DateTime(2014,3,27,7,5,0);
str = t.ToString("H:mm");
Console.WriteLine(str);
The HH format return always the hour formatted with two digits adding a leading zero when the hour is less than 10, the H format returns the hours formatted with exactly the digits present in the hour part.
You can create an instance of DateTime with desired date and time values using to test various time setting and formats :
var dt = new DateTime(2014, 1, 1, 7, 35, 0);
string str = dt.ToString("HH:mm");
I have date/time format, for example:
"1-Mar-13 92230"
According to this document and this link the format is as follows:
"d-MMM-yy Hmmss", because:
Day is single digit, 1-30
Month is 3 letter abbreviation, Jan/Mar etc.
Year is 2 digits, eg 12/13
Hour is single digit for 24 hour clock, eg 9, 13 etc. (no 09)
Minute is standard (eg 01, 52)
Second is standard (eg 30, 02)
I'm trying to run the following code in my program, but I keep getting an error of "String was not recognized as a valid DateTime."
string input = "1-Mar-13 92330";
var date = DateTime.ParseExact(input, "d-MMM-yy Hmmss",
System.Globalization.CultureInfo.CurrentCulture);
Please help, I'm not too familiar with DateTime conversions, but I can't see where I've gone wrong here. Thanks!
UPDATE: Is this because time cannot be parsed without colons in between? (eg 1-Mar-13 9:22:30 gets parsed, but i have an external data source that would be impossible to rewrite from Hmmss to H:mm:ss)
You could fix your date:
var parts = "1-Mar-13 92230".Split(' ');
if (parts[1].Length == 5)
{
parts[1] = "0" + parts[1];
}
var newDate = parts[0] + " " + parts[1];
var date = DateTime.ParseExact(newDate, "d-MMM-yy HHmmss", System.Globalization.CultureInfo.CurrentCulture);
From msdn:
If format is a custom format pattern that does not include date or
time separators (such as "yyyyMMdd HHmm"), use the invariant culture
for the provider parameter and the widest form of each custom format
specifier. For example, if you want to specify hours in the format
pattern, specify the wider form, "HH", instead of the narrower form,
"H".
so you can try:
string input = "1-Mar-13 92330";
var date = DateTime.ParseExact(input, "d-MMM-yy Hmmss",
System.Globalization.CultureInfo.InvariantCulture);
Your input string has to be of following format
string input = "1-Mar-13 092330";
If you go back to your link, it says
H 24-hour clock hour (e.g. 19)
Now H is 24 hours, it should be represented with leading 0. If not imagine how would you handle the case of hours greater than 9 i.e which are in double digit.
If not your hour and Minute and Seconds has to be separated.
string input = "1-Mar-13 9 2330";
var date = DateTime.ParseExact(input, "d-MMM-yy H mmss",
System.Globalization.CultureInfo.InvariantCulture);
Your hour min and seconds need to be separated, as they are not getting distinguished.
string input = "1-Mar-13 9 23 30";
var date = DateTime.ParseExact(input, "d-MMM-yy H mm ss", System.Globalization.CultureInfo.CurrentCulture);