DateTime ConvertTimeBySystemTimeZoneId isn't working - c#

I save time to UTC in database.
And I want convert time to local time zone when get time data from database.
Here is function.
public static List<string> convertListDateTime(List<string> timelist, TimeZoneInfo local)
{
for (int i = 0; i < timelist.Count; i++)
{
DateTime dt = DateTime.Parse(timelist[i]);
dt = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(dt, local.Id);
timelist[i] = dt.ToString("yyyy-MM-dd HH:mm:ss");
}
return timelist;
}
timelist is string list that has data from database.
But timelist is not change. It is the same as the database data.
How can I do?

This is the first problem:
DateTime dt = DateTime.Parse(timelist[i]);
You haven't said that the value is in UTC, so it's assumed to be in local time. A conversion from that to local time is a no-op. You can fix that when parsing by saying that the input is in UTC and you want the output to be in UTC too:
DateTime dt = DateTime.ParseExact(
timelist[i],
"yyyy-MM-dd HH:mm:ss",
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
But secondly, you should try to avoid all this string conversion anyway: if you store the values in the database as DateTime values instead of strings, that makes things a lot easier.
I would try to use the values as DateTime values as far as possible too - only convert to strings when you absolutely have to, and ideally not as part of an operation which is also performing time zone changes.
Finally, rather than using ConvertTimeBySystemTimeZoneId, if you've already got a TimeZoneInfo you can use that directly:
DateTime convertedValue = TimeZoneInfo.ConvertTimeFromUtc(utcValue, zoneInfo);

Related

DateTime local and utc the same

I am sending from webbrowser this string "2019-01-25T00:00:00+01:00"
I undestand this as: this is local time and in utc should be "2019-01-24T23:00:00"
but on the server :
myDate.Kind is local
myDate "2019-01-24T23:00:00"
myDate.ToLocalTime() is the same "2019-01-24T23:00:00"
myDate.ToUniversalTime() is the same "2019-01-24T23:00:00"
what I need is if I sent this string "2019-01-25T00:00:00+01:00" I need to know on the server that there is 1h difference between local and utc
and parsing this string is done automatically by dot net core api (DateTime is method parameter)
The DateTime Type does not have any concept of time zones: if you need this, use DateTimeOffset instead.
I suspect your server is in the UTC timezone, Since ToLocalTime and ToUniversalTime give the same result.
You can try AdjustToUniversal option, e.g.
string source = "2019-01-25T00:00:00+01:00";
DateTime myDate = DateTime.ParseExact(
source,
"yyyy-MM-dd'T'HH:mm:sszzz",
CultureInfo.InvariantCulture,
DateTimeStyles.AdjustToUniversal);
Console.Write(string.Join(Environment.NewLine,
$"Value = {myDate:HH:mm:ss}",
$"Kind = {myDate.Kind}"));
Outcome:
Value = 23:00:00
Kind = Utc
Edit: If you can't change server's code and thus you have to provide a string (source) such that DateTime.Parse(source)
will return a correct date you can try to convert existing time-zone (+01:00) into Zulu:
string source = "2019-01-25T00:00:00+01:00";
// 2019-01-24T23:00:00Z
source = DateTime
.ParseExact(source,
"yyyy-MM-dd'T'HH:mm:sszzz",
CultureInfo.InvariantCulture,
DateTimeStyles.AdjustToUniversal)
.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'");
Then on the server you'll have
// source is treated as UTC-time;
// However, by default (when no options provided) myDate will have Kind = Local
DateTime myDate = DateTime.Parse(source);
Console.Write(string.Join(Environment.NewLine,
$"Value = {myDate:HH:mm:ss}",
$"Kind = {myDate.Kind}"));
Outcome:
Value = 02:00:00 // May vary; adjusted to server's time zone (In my case MSK: +03:00)
Kind = Local // DateTime.Parse returns Local when no options specified

ASP.NET MVC convert DateTime to UTC to send to API

I need to send a start date and end date to an API in UTC format, I have tried the following:
DateTime startDate = Convert.ToDateTime(start + "T00:00:00Z").ToUniversalTime();
DateTime endDate = Convert.ToDateTime(end + "T23:59:59Z").ToUniversalTime();
But it appears they are not converting to UTC, what would be the proper way to take startDate and endDate and convert them over to UTC?
start is a string and is 2018-08-31 and end date is also a string and is 2018-08-31 I added the times in the code above to cover the full date.
Assuming you want endDate to represent the last possible moment on the given date in UTC:
DateTime startDate = DateTime.ParseExact(start, "yyyy-MM-dd", CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
DateTime endDate = DateTime.ParseExact(end, "yyyy-MM-dd", CultureInfo.InvariantCulture,
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)
.AddDays(1).AddTicks(-1);
A few other things:
ToUniversalTime converts to UTC from the computer's local time zone (unless .Kind == DateTimeKind.Utc). You should generally avoid it unless the computer's local time zone is relevant to your situation.
In the above code, you need both AssumeUniversal to indicate that the input date is meant to be interpreted as UTC, and AdjustToUniversal to indicate that you want the output value to be kept in terms of UTC and not the computer's local time zone.
UTC is not a "format". Your combined date and time strings would be in ISO 8601 extended format (also RFC 3339 compliant).
Generally, try not to use Convert.ToDateTime. It is equivalent to DateTime.Parse with CultureInfo.CurrentCulture and no DateTimeStyles. That may work for some scenarios, but it is usually better to be more specific.
.AddDays(1).AddTicks(-1) is there to get you to the last representable tick on that date. That allows for inclusive comparison between start and end, however it comes with the disadvantage of not being able to subtract the two values and get a whole 24 hours. Thus, it is usually better to simply track 00:00 of one day to 00:00 of the next day, then use exclusive comparison on the end date. (Only the start date should be compared inclusively.)
In other words, instead of:
2018-08-31T00:00:00.0000000Z <= someValueToTest <= 2018-08-31T23:59:59.9999999Z
Do this:
2018-08-31T00:00:00.0000000Z <= someValueToTest < 2018-09-01T00:00:00.0000000Z
First install below package from NuGet package manager and referenced it in your project:
Install-Package Newtonsoft.Json
Now you can easily use JsonConvert.SerializeObject(object value) method for serialize any objects to Json.
For converting DateTime to UTC use TimeZoneInfo.ConvertTimeToUtc(DateTime dateTime) method.
In your case:
DateTime date = DateTime.Parse("2018-08-31");
DateTime dateTimeToUtc = TimeZoneInfo.ConvertTimeToUtc(date);
string dateInJson = JsonConvert.SerializeObject(dateTimeToUtc);
the variable dateInJson will have value like 2018-08-30T19:30:00Z.
Remove the Z
string start = "2018-08-31";
string end = "2018-08-31";
DateTime startDate = Convert.ToDateTime(start + "T00:00:00");
DateTime endDate = Convert.ToDateTime(end + "T23:59:59");
Console.WriteLine(startDate); // 8/31/2018 12:00:00 (Local)
Console.WriteLine(startDate.ToUniversalTime()); // 8/31/2018 5:00:00 (UTC)
Console.WriteLine(endDate); // 8/31/2018 11:59:59 (Local)
Console.WriteLine(endDate.ToUniversalTime()); // 9/1/2018 4:59:59 (UTC)
In case you are sending dynamic linq like me, you'd need datetime in a text form.
If you are dealing with UTC then:
//specify utc just to avoid any problem
DateTime dateTime = yourDateTime.SetKindUtc();
var filterToSendToApi = $"CreatedTime>={dateTime.ToStringUtc()}"
helpers:
public static string ToStringUtc(this DateTime time)
{
return $"DateTime({time.Ticks}, DateTimeKind.Utc)";
}
public static DateTime SetKindUtc(this DateTime dateTime)
{
if (dateTime.Kind == DateTimeKind.Utc)
{
return dateTime;
}
return DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);
}

DateTime.Now in C# to yield Datetime2(3) in SQL Server datatype

I tried several ways to retrieve datetime2(3) equivalent from C# code but in vain.
One of them is as follows.
DateTime dt = DateTime.Now.AddMilliseconds(DateTime.Now.Millisecond);
I need the following format:
YYYY-MM-DD HH:MM:SS.FFF
But from the above code, I got the following result
6/19/2012 11:15:08 PM
When I tried the following way,
string myTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff");
DateTime dd = Convert.ToDateTime(myTime);
it is throwing following error
String was not recognized as a valid DateTime.
I need the date in datetime2(3) format only instead you can suggest me to save as nvarchar. But I need to sort the entries according to the datetime2 they were updated.
Is there any other way to solve this?
var format = "yyyy-MM-dd HH:mm:ss:fff";
var stringDate = DateTime.Now.ToString(format);
var convertedBack = DateTime.ParseExact(stringDate, format, CultureInfo.InvariantCulture);
DateTime is a data type representing dates and times and does not store format information. The milliseconds are always stored in DateTime. The only time you need to specify milliseconds is when choosing how to represent the DateTime as another type, like a string.

Combine date and time when date is a DateTime and time is a string

I am working with an old mysql database in which a date is stored (without a time) as a datetime and a time is stored as a string (without a date).
In C# I then have a DateTime with a value like 2010-06-25 12:00:00 AM and a String with a value like 15:02.
What is the most concise way to combine these without a lot of overhead?
I have tried a few methods including:
DateTime NewDateTime = DateTime.Parse(OldDateTime.ToString("yyyy-MM-dd ") + TimeString);
I dislike converting the existing DateTime to a string and appending the time.
I can convert the time string to a date, but then I get today's date and adding it as a number of ticks to the old datetime is incorrect.
Note: Don't worry about validation, it is done elsewhere. The time is represented using 24-hour format without seconds.
You can use TimeSpan.Parse to parse the time, and then add the result to the date:
DateTime newDateTime = oldDateTime.Add(TimeSpan.Parse(timeString));
var dt = new DateTime(2010, 06, 26); // time is zero by default
var tm = TimeSpan.Parse("01:16:50");
var fullDt = dt + tm; // 2010-06-26 01:16:50
I used something similar to what simendsjo says, except I continued to have it as a DateTime
DateTime date = Convert.ToDateTime(txtTrainDate.Text);
DateTime time = Convert.ToDateTime(ddTrainTime.SelectedValue);
DateTime dtCOMPLTDTTM = new DateTime(date.Year, date.Month, date.Day, time.Hour, time.Minute, time.Second);
I think you're worrying about the string conversion too much. By combining the 2 string elements together you are saving further date string parsing anyway which will most likely be more expensive.
Is this going to be repeated a lot of times or a simple step in a larger process?
I am fairly sure you could combine and convert these values into a timestamp using SQL.

convert string to date without time

This line
System.DateTime.Parse("09/12/2009");
convert date (string) to 9/12/2009 12:00:00 AM. How can I get a date in the form 9/12/2009.
after explanations I do:
DateTime dt = System.DateTime.Parse(Request.Form["datepicker"]);
dt.ToString("dd/mm/yyyy");
/* and this code have time, why???*/
Your problem is not with the parsing but with the output. Look at how ToString works for DateTime, or use this example:
using System;
class Program
{
static void Main(string[] args)
{
DateTime dt = DateTime.Parse("09/12/2009");
Console.WriteLine(dt.ToString("dd/MM/yyyy"));
}
}
Or to get something in your locale:
Console.WriteLine(dt.ToShortDateString());
Update: Your update to the question implies that you do not understand fully my answer yet, so I'll add a little more explanation. There is no Date in .NET - there is only DateTime. If you want to represent a date in .NET, you do so by storing the time midnight at the start of that day. The time must always be stored, even if you don't need it. You cannot remove it. The important point is that when you display this DateTime to a user, you only show them the Date part.
Anything parsed to a DateTime object will contain date+time. If no time is sepcified, the assumed value will be 0000hr.
To get the date-only representation, it's up to how you format it to string.
E.g. theDate.ToString("dd/MM/yyyy")
Refer to the MSDN Date and Time Format Strings.
if you want to convert gridview datetime column to date only column use this code :
raddgvDaybook.Rows.ToList().ForEach(x =>
{
DateTime dt = DateTime.Parse(x.Cells["Vocdate"].Value.ToString());
string str = string.Format("{0:MM/dd/yyyy}", dt);
x.Cells["Vocdate"].Value = str;
});
I tested the code it will work if you bind the datetime as string in dgv.

Categories