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.
Related
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'm writing c# custom sonarqube rules. I'm trying to match a string literal in the code which is exactly like "dd/mm/yyyy".
I mean whenever developer used dd/mm/yyyy or mm/dd/yyyy or yyyy/mm/dd it should catch..
I need regular expression for this in c# to match the "dd/mm/yyyy or mm/dd/yyyy or yyyy/mm/dd"
As I wrote in the comments, you have a much bigger problem - your allowed formats are colliding - There is no way to distinguish between dd/mm/yyyy and mm/dd/yyyy if the day is lower than 13.
Also, validating date formats can easily be achieved using DateTime.TryParseExact so there really is no need to write a big, hard to read, hard to maintain regular expression for that.
Check out this demo program (click to run) I've written to illustrate what I mean:
public class Program
{
public static void Main(string[] args)
{
string[] dates = {
// Valid dates
"01/02/2018", // January 2nd (mm/dd/yyyy)
"04/01/2018", // January 4th (dd/mm/yyyy)
"20/01/2018", // January 20th (dd/mm/yyyy)
"01/21/2018", // January 21st (mm/dd/yyyy)
"2018/01/14", // January 14th (yyyy/mm/dd)
// Invalid dates
"23/13/2018",
"not a date",
"2018/22/01",
"1/1/18"
};
string[] formats = {"dd/MM/yyyy", "MM/dd/yyyy", "yyyy/MM/dd"};
for(var i = 0; i < dates.Length; i++)
{
DateTime dateTime;
if(DateTime.TryParseExact(dates[i], formats, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out dateTime))
{
Console.WriteLine(dates[i] + " is a valid date: "+ dateTime.ToString("yyyy-MM-dd") );
}
else
{
Console.WriteLine(dates[i] + " is invalid.");
}
}
}
}
And the results:
01/02/2018 is a valid date: 2018-02-01
04/01/2018 is a valid date: 2018-01-04 // Note: Wrong date! should be January 4th!
20/01/2018 is a valid date: 2018-01-20
01/21/2018 is a valid date: 2018-01-21
2018/01/14 is a valid date: 2018-01-14
23/13/2018 is invalid.
not a date is invalid.
2018/22/01 is invalid.
1/1/18 is invalid.
So, having written all that - the correct solution is to avoid string representation of datetime whenever possible, and if you really must allow that, you need to make sure you only allow a well defined set of formats that are not colliding each other - dd/mm/yyyy and yyyy/mm/dd are fine, if you want to add another option you can choose a different delimiter to help you correctly distinguish the values - dd/mm/yyyy and mm-dd-yyyy can live together quite happily, for instance.
Tihs regex will work for YYYY/MM/DD and DD/MM/YYYY:
((?=\d{4})\d{4}|(?=[a-zA-Z]{3})[a-zA-Z]{3}|\d{2})((?=\/)\/|\-)((?=[0-9]{2})[0-9]{2}|(?=[0-9]{1,2})[0-9]{1,2}|[a-zA-Z]{3})((?=\/)\/|\-)((?=[0-9]{4})[0-9]{4}|(?=[0-9]{2})[0-9]{2}|[a-zA-Z]{3})
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.
i want to calculate a checktime to the time now and get the hours.
I have a string "time" for example...
Jun 06 2013 07:23:06
and with DateTime.Now I get the Time now. The Problem is now that i can't calculate the difference :(
I need them in my Project where I get from the License Server the time from a user and I want to show the difference to now. I want show this in hours.
You can use the Parse method of the DateTIme class to parse a string as a date and the subtract that from now.
TimeSpan diff = DateTime.Now - DateTime.Parse(dateString);
var hours = diff.Hours
The above exsmple of course requires the date to be in a specific format. You can if needed use DateTIme.ParseExact and specify a specific format yourself
You need to first convert your string to DateTime. here you have custom format so you can use DateTime.ParseExact or DateTime.TryParseExact method as below
DateTime dt;
if (DateTime.TryParseExact("Jun 06 2013 07:23:06", "MMM dd yyyy HH:mm:ss", CultureInfo.InvariantCulture,
DateTimeStyles.None, out dt))
{
// get difference
var inDays = (DateTime.Now - dt).Days;
}
You can use TimeSpan.Hours property like;
Gets the hours component of the time interval represented by the
current TimeSpan structure.
string dateString = "Jun 06 2013 07:23:06";
var differenceHours = (DateTime.Now - DateTime.Parse(dateString)).Hours;
Console.WriteLine(differenceHours);
Here a DEMO.
If you want to convert your custom formatted string to DateTime, you can use DateTime.ParseExact which need exact format matching between string and datetime.
Converts the specified string representation of a date and time to its
DateTime equivalent. The format of the string representation must
match a specified format exactly or an exception is thrown.
u may try it
DataTime diff = DateTime.Now - Convert.ToDataTime(dateString);
var hours = diff.Hours
i am having an input string of HH:MM:SS for example 15:43:13,
now i want to convert it to datetime but keep just the hour/time without the date etc
is it possible?
for example
string userInput = 15:43:13;
DateTime userInputTime = Convert.ToDateTime(userInput);
will give me the full date including the year etc,
is there any way to convert it to just HH:MM:SS without triming/substring?
thanks
As others have said, it's a TimeSpan.
You can get a datetime by doing this
string userInput = "15:43:13";
var time = TimeSpan.Parse(userInput);
var dateTime = DateTime.Today.Add(time);
To just get a time span, you can use:
TimeSpan.Parse("15:43:13")
But you should ask yourself why you want to do this as there are some fairly significant gotchas. For example, which 2:33 AM do you want when it's Sunday, November 3, 2013, and daylight savings time is ending? There are two of them.
If you don't need the extra data (year etc.) use TimeSpan
You can convert from the user input to a TimeSpan using Timespan.Parse
for example:
TimeSpan ts = TimeSpan.Parse("6:12"); //06:12:00
Read more here:
http://msdn.microsoft.com/en-us/library/se73z7b9.aspx