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:-)
Related
I've got a string in the following format: 05/06/2019|1330|60
The output I'm looking for is: 05/06/2019T14:30:00
I'm attempting to parse out the TimeSpan portion right now:
public static string getProcedureEndingDateTime (string input) {
//05/06/2019|1330|60
string myDate = input.Split ( '|' ) [0];
DateTime myDateTime = DateTime.Parse (myDate);
string myTime = input.Split('|')[1];
string hours = myTime.Substring(0,2);
string minutes = myTime.Substring(2,2);
TimeSpan myTimeSpan = TimeSpan.Parse($"{hours}:{minutes}");
myDateTime.Add(myTimeSpan);
return myDateTime.ToString();
}
But right now, getting the following output:
To get the above output I'm calling my function like so:
Console.WriteLine (getProcedureEndingDateTime("05/06/2019|1330|60"));
How do I parse the string "1330" into a TimeSpan?
No need to us a Timespan here, just call ParseExact instead with a proper format to do it in one line.
var myDateTime = DateTime.ParseExact("05/06/2019|1330|60", "dd/MM/yyyy|HHmm|60", CultureInfo.InvariantCulture);
Console.WriteLine(myDateTime.ToString());
//this gives 2019-06-05 1:30:00 PM, format depends on your PC's locale
I don't know what the 60 part is, you can adjust the format or substring it out beforehand.
The problem is because Add() returns a new DateTime instance, which means you're currently discarding it. Store it, and return that from your function instead, like so:
var adjusted = myDateTime.Add(myTimeSpan);
return adjusted.ToString();
Try using the numeric values as exactly that, numbers.
Also, the other issue with your code is the DateTime.Add() method doesn't add to that DateTime variable. Instead it returns a new variable, which you are ignoring.
Try this:
public static string getProcedureEndingDateTime (string input) {
string[] parts = input.Split('|');
string myDate = parts[0];
DateTime myDateTime = DateTime.Parse (myDate);
string myTime = parts[1];
if (!int.TryParse(myTime.Substring(0,2), out int hours))
hours = 0;
if (!int.TryParse(myTime.Substring(2,2), out int minutes))
minutes = 0;
TimeSpan myTimeSpan = new TimeSpan(hours, minutes, 0);
myDateTime += myTimeSpan;
return myDateTime.ToString();
}
Assuming the date shown is May 6th (and not June 5th), and also assuming the 60 represents a time zone offset expressed in minutes west of GMT, and also assuming you want the corresponding UTC value, then:
public static string getProcedureEndingDateTime (string input) {
// example input: "05/06/2019|1330|60"
// separate the offset from the rest of the string
string dateTimeString = input.Substring(0, 15);
string offsetString = input.Substring(16);
// parse the DateTime as given, and parse the offset separately, inverting the sign
DateTime dt = DateTime.ParseExact(dateTimeString, "MM/dd/yyyy|HHmm", CultureInfo.InvariantCulture);
TimeSpan offset = TimeSpan.FromMinutes(-int.Parse(offsetString));
// create a DateTimeOffset from these two components
DateTimeOffset dto = new DateTimeOffset(dt, offset);
// Convert to UTC and return a string in the desired format
DateTime utcDateTime = dto.UtcDateTime;
return utcDateTime.ToString("MM/dd/yyyy'T'HH:mm:ss", CultureInfo.InvariantCulture);
}
A few additional points:
Not only is the input format strange, but so is your desired output format. It is strange to see a T separating the date and time and also see the date in the 05/06/2019 format. T almost always means to use ISO 8601, which requires year-month-day ordering and hyphen separators. I'd suggest either dropping the T if you want a locale-specific format, or keep the T and use the standard format. Don't do both.
In ISO 8601, it's also a good idea to append a Z to UTC-based values. For DateTime values, the K specifier should be used for that. In other words, you probably want the last line above to be:
return utcDateTime.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// outputs: "2019-05-06T14:30:00Z"
You might want to not format a string here, but instead return the DateTime or DateTimeOffset value. It's usually better to create a string only at the time of display.
Don't forget that the DateTime struct is immutable. In your question you were ignoring the return value of the Add method.
Using ASP.NET Forms, I'm encountering a problem with converting a 12 hour time into a timespan. Below I'm combining DateTime with TimeSpan as the user chooses a date and then a time. The fields are controlled by javascript.
DateTime DateResult = DateTime.TryParse(txtDate.Text, out DateResult) ? DateResult : DateTime.Today;
TimeSpan TimeResult = TimeSpan.TryParseExact(txtTime.Text, "h:mm tt", CultureInfo.InvariantCulture, out TimeResult) ? TimeResult : new TimeSpan();
DateResult = DateResult.Add(TimeResult)
So parsing the date works fine, but Timespan doesn't. One example:
Date Entered: 08/03/2018
Time Entered: 3:00 AM
Values are gettined passed okay but time fails so DateResult becomes "08/03/2018 00:00" but not "08/03/2018 03:00". I have also tried using the method TimeSpan.TryParse but no luck with that one.
I've also made sure that the format is correct by manually entering the time in the database behind the scenes. The gridview has a column that shows the full date in this format "dd/MM/yyyy h:mm tt", and works.
Anyone please share some light? Ideally, I would like to avoid any third party plug-ins.
Parse them together
Simplest thing is to just concatenate the strings before parsing as a single DateTime, e.g.
var dateEntered = #"08/03/2018";
var timeEntered = #"3:00 am";
DateTime result;
var completeDateString = dateEntered + " " + timeEntered;
var ok = DateTime.TryParse(completeDateString, out result);
if (!ok) result = DateTime.Today;
Console.WriteLine(result);
Output:
8/3/2018 3:00:00 AM
Ta da
If you have to parse them separately
If you'd like to work with the fields separately, you still can (I guess you'd have to do this if you want the time format to be exact but the date portion to be flexible, as it is in your example). But TimeSpan.TryParseExact is really different from DateTime.Parse. The format codes are different; it doesn't support the ":" character (except as a literal with an escape, e.g. "\:"), for example, or the "tt" formatting specifier. I'm guessing the concept of am/pm has to do with an absolute point in time, not a relative time offset, so isn't provided for. But you can still parse the textbox as a DateTime and use its time portion.
You can probably shorten this a bit but this example gives you everything you need:
static public DateTime ParseDateTime(string input)
{
DateTime output;
var ok = DateTime.TryParse(input, out output);
if (ok) return output;
return DateTime.Today;
}
static public TimeSpan ParseTime(string input)
{
DateTime output;
var ok = DateTime.TryParseExact(input, #"h:mm tt", CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.NoCurrentDateDefault, out output);
return output.Subtract(output.Date);
}
public static void Main()
{
var dateEntered = #"08/03/2018";
var timeEntered = #"3:00 am";
DateTime dateResult = ParseDateTime(dateEntered);
TimeSpan timeResult = ParseTime(timeEntered);
DateTime finalResult = dateResult.Add(timeResult);
Console.WriteLine(finalResult);
}
Output:
8/3/2018 3:00:00 AM
Code on DotNetFiddle
See ParseExact or https://msdn.microsoft.com/en-us/library/system.timespan.tryparseexact(v=vs.110).aspx for TryParseExact should work for both DateTime as well as TimeSpan inter alia
Fyi it's called the meridian and see also AM/PM to TimeSpan
I have datetime string
dateStr = "2017-03-21T23:00:00.000Z";
then I am calling
var date = DateTime.Parse(dateStr);
and unexpectedly my date equals
22.03.2017 00:00:00
I expected it to be 21.03.2017
What's going on here?
DateTime.Parse() is locale specific and will take into account your local time zone when parsing dates.
If you are in CET (Central European Time) during the winter your offset is one hour ahead of UTC. The date given is marked with a Z indicating it is in UTC, so DateTime.Parse() will adjust that to your local timezone.
There is an override that allows you to change that behaviour if you want, by specifying a specific DateTimeStyles enum. DateTimeStyles.AdjustToUniversal is what you are looking for as that should keep the DateTime as UTC.
And if you only want the date part afterwards, you can just call .Date on the DateTime object you got back from Parse()
So, something like this:
var date = DateTime.Parse(dateStr, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal).Date;
if the date format does not change then you can use the below code to get date part from date string. But it is a bit risky due to its strict dependency on the input format.
string dateStr = "2017-03-21T23:00:00.000Z";
int year = Int32.Parse(dateStr.Substring(0, 4));
int month = Int32.Parse(dateStr.Substring(5, 2));
int day = Int32.Parse(dateStr.Substring(8, 2));
var date = new DateTime(year, month, day);
Console.WriteLine(date);
Because the format of type 'DateTime' variable is 'YYYY-MM-DD hh:mm:ss'.
If you run this code:
var dt = DateTime.Now;
Console.WriteLine(dt);
You'll see '24/03/2017 12:54:47'
If you have 'YYYY-MM-DD' format, add .ToString("dd-MM-yyyy"), then:
string dateStr = "2017-03-21T23:00:00.000Z";
var date = DateTime.Parse(dateStr).ToString("dd-MM-yyyy");
Result:'24-03-2017'
I've tried with several different format strings but I can't get it to parse a date like:
date = "10/16/13";
DateTime endDate = DateTime.ParseExact(date, "M-dd-yy", CultureInfo.InvariantCulture);
What am I missing?!
For it to parse the date your format needs to be the same. Change "M-dd-yy" to "M/dd/yy" Assuming that the month is a single digit and the day is always 2 digits.
Here you go this should work just fine. You just need to be aware that it will set a default time of 12:00 am because you are not specifying the time in your string.
class Program
{
static void Main(string[] args)
{
string date = "10/16/13";
//This is usually the safer way to go
DateTime result;
if(DateTime.TryParse(date, out result))
Console.WriteLine(result);
//I think this is what you were trying to accomplish
DateTime result2 = Convert.ToDateTime(date, CultureInfo.InvariantCulture);
Console.ReadKey();
}
}
If I have a timestamp in the form: yyyy-mm-dd hh:mm:ss:mmm
How can I just extract the date from the timestamp?
For instance, if a timestamp reads: "2010-05-18 08:36:52:236" what is the best way to just get 2010-05-18 from it.
What I'm trying to do is isolate the date portion of the timestamp, define a custom time for it to create a new time stamp. Is there a more efficient way to define the time of the timestamp without first taking out the date, and then adding a new time?
DateTime.Parse("2010-05-18 08:36:52:236").ToString("yyyy-MM-dd");
You should use the DateTime type:
DateTime original = DateTime.Parse(str);
DateTime modified = original.Date + new TimeSpan(13, 15, 00);
string str = modified.ToString("yyyy-MM-dd HH:mm:ss:fff");
Your format is non-standard, so you'll need to call ParseExact instead of Parse:
DateTime original = DateTime.ParseExact(str, "yyyy-MM-dd HH:mm:ss:fff", CultureInfo.InvariantCulture);
You could use substring:
"2010-05-18 08:36:52:236".Substring(0, 10);
Or use ParseExact:
DateTime.ParseExact("2010-05-18 08:36:52:236",
"yyyy-MM-dd HH:mm:ss:fff",
CultureInfo.InvariantCulture)
.ToString("yyyy-MM-dd");
DateTime date;
if (DateTime.TryParse(dateString, out date))
{
date = date.Date; // Get's the date-only component.
// Do something cool.
}
else
{
// Flip out because you didn't get a real date.
}
Get the .Date member on the DateTime
DateTime date = DateTime.Now;
DateTime midnightDate = date.Date;
use it like this:
var x = DateTime.Now.Date; //will give you midnight today
x.AddDays(1).AddTicks(-1); //use these method calls to modify the date to whats needed.
The best (and fastest) way to do this is to convert the date to an integer as the time part is stored in the decimal part.
Try this:
select convert(datetime,convert(int, #yourdate))
So you convert it to an integer and then back to a data and voila, time part is gone.
Of course subtracting this result from the original value will give you the time part only.