Convert UTC to local time with daylight saving on rdlc report - c#

I pick up data which includes some date columns. Date returned from database is in UTC format. I feed this data to report viewer and want to show the date in local format, considering daylight saving.
I can do that from server side but I want the conversion to be according to the client machine timezone.
Is there any way to do it ?

Is your client a web page or a .NET app? If it is a .NET app you could do it like this. Firstly send your client timezone to your server like so:
string clientTimeZone = TimeZoneInfo.Local.ToSerializedString();
Then on your server:
var clientTimeZoneInfo = TimeZoneInfo.FromSerializedString(clientTimeZone);
var localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, clientTimeZoneInfo);
If this is a webapp use this javascript to send the offset to the server:
var timeNow = new Date();
var timezone = timeNow.getTimezoneOffset() / 60 * (-1);
Then on your server:
string clientTimeZoneOffset = "8";
var clientTimeZoneInfo = TimeZoneInfo.CreateCustomTimeZone("client", new TimeSpan(0, Int32.Parse(clientTimeZoneOffset), 0, 0),
"client", "client");
var utcDateTime = DateTime.UtcNow;
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, clientTimeZoneInfo);

Related

Changing Date Format to dd/MM/yyyy After conversion from Timezone

I am working on a project that requires me to be comparing the date stored as string in database to the current date.
This particular application works in localhost but on live server, it seems to be picking the date of the server. I am resident in West Central Africa. How do i get the Date returned by my converted timezone in the format dd/MM/yyyy and not MM/dd/yyyy that it is seeing it.
Below is a code snippet.
var date = DateTime.UtcNow ;
var zone = TimeZoneInfo.FindSystemTimeZoneById("W. Central Africa Standard Time");
DateTime currentTime = TimeZoneInfo.ConvertTimeFromUtc(date, zone);
var loanDates = currentTime.Date;
var OldloanDate = loanDates.ToShortDateString();
var nloanDate = DateTime.ParseExact(OldloanDate, "dd/MM/yyyy", CultureInfo.InvariantCulture).Date;
var loanDate = nloanDate.ToShortDateString();
I want the loanDate to be in string form and of the format dd/MM/yyyy
You can try this:
var date = DateTime.UtcNow;
var zone = TimeZoneInfo.FindSystemTimeZoneById("W. Central Africa Standard Time");
var currentTime = TimeZoneInfo.ConvertTimeFromUtc(date, zone);
var loanDate = currentTime.Date.ToString("dd/MM/yyyy").Replace("-", "/");

What are valid UTCDateTime type string formats for AIF transfomrmations?

Im am trying to write a .net class that transforms a piece of xml to a AX UtcDateTime type.
The class is used in an inbound transformation.
Original xml:
<DateTime>
<Date>2014-06-12</Date>
<Time>10:52:00</Time>
<Zone>+02:00</Zone>
</DateTime>
My resulting xml leads to an exeption in the exeptionlog:
"The value '2014-06-12T12:52:00+02:00' is not a valid UtcDateTime type."
I think AIF expect the Z at the end of the value, and I am not sure if the localDateTime is mandatory and or if the milliseconds are a requirement.
I would like to know how the UtcDateTime field in transformed xml should be formatted to be accepted by AIF.
Like so:
<MessageHeaderDateTime localDateTime="2014-06-12T10:52:00+02:00">2014-06-12T08:52:00Z</MessageHeaderDateTime>
or like so:
<MessageHeaderDateTime localDateTime="2014-06-12T10:52:00.1108723+02:00">2014-06-12T08:52:00.1108723Z</MessageHeaderDateTime>
or are other things missing?
My Code
DateTime netdttm = new DateTime(year, month, day, hour, minute, second, DateTimeKind.Utc);
TimeSpan timespan = new TimeSpan(zhour, zminute, 0);
DateTime netdttmoffset = netdttm.Subtract(timespan);
datetime.Value = netdttmoffset;
datetime.localDateTime = netdttmoffset.ToLocalTime();
datetime.localDateTimeSpecified = true;
I use a similar appraoch for the case where I use utcnow.
Problem i that I have limited testing possibilities due to hot-swapping being disbled in the environment where I have to develop my code. So I would like to be certainin about the formatting.
Thanx for your help.
I finally got it to work. My solution:
//declare the AX utcdatetime type from the cs class generate with:
//xsd C:\...\SharedTypes.xsd C:\..\AIFschema.xsd /Classes /Out:C:\location\of\csfile\
AxType_DateTime datetime = new AxType_DateTime();
//Ax store the time in GMT with an optional local time. My XML can have any timezone.
datetime.timezone = AxdEnum_Timezone.GMT_COORDINATEDUNIVERSALTIME;
//I set this to false as i am not interested in actually storing the local time. Plus AX fails over the formatting .net returns.
datetime.timezoneSpecified = false;
//{... left out code to retrieve the hours, minutes etc from my XML}
//declare the .net datetime variable with the values from the xml:
DateTime netdttm = new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc);
DateTime netdttmoffset = new DateTime();
// (optional field) <zone>+01:00</zone>
if (message.Header.DateTime.Zone != null)
{
{... left out code to retrive zone offset info from xml}
TimeSpan timespan = new TimeSpan(zhour, zminute, 0);
netdttmoffset = netdttm.Subtract(timespan);
}
else //no zone, so datetime == GMT datetime.
{
netdttmoffset = netdttm;
}
datetime.Value = netdttmoffset;
datetime.localDateTime = netdttmoffset.ToLocalTime();
//do not output to xml, or AX will fail over this.
datetime.localDateTimeSpecified = false;
Result xml snippet as accepted by AX:
<MessageHeaderDateTime>2014-07-30T16:41:10.001Z</MessageHeaderDateTime>
I found this to be easier. If you want a particular datetime, say Jan 31, 2015 8:00 am, to be stored in AX, the .net code to make it happen would be
DateTime utcDateTime = new DateTime(2015, 1, 31, 8, 0, 0).ToUniversalTime();
var workerStartDate = new AxdExtType_HcmEmploymentStartDateTime
{
Value = utcDateTime
};
The XML generated would be would be <WorkerStartDate>2015-05-12T13:00:00Z</WorkerStartDate>, assuming you are 5 hours behind GMT on the computer that runs the .net code. The AX database will store the value 2015-05-12T13:00:00Z as well.
<dyn:StartDate>2014-06-22T00:00:00.000+02:00</dyn:StartDate>
This format always does the trick for me. (Notice the ms)

convert date time to client time zone taking care of dst

i have date in pst format in database and i am passing it from backend via C# to javascript and then trying to convert it to client local time and here is the code i am using to convert it
onverttDate: function (element,date)
{
var Element = $(element);
var d1 = new Date(date);
var newDate = new Date(d1.getTime() + d1.getTimezoneOffset() * 60 * 1000);
var offset = d1.getTimezoneOffset() / 60;
var hours = d1.getHours();
newDate.setHours(hours offset);
Element.append('<div>' + newDate + '</div>');
}
and the date string i am getting from backend to javascript function is May 24,2014 09:59:59 and the converted date should be May 24,2014 22:59:59
i am not able to spot bug,i tried using moment.js also but its also not working.
Please give me a solution for this as what i am doing wrong.
Any, js fiddle example hardcoding date string as it is will also be appreciated
Note:I am getting date string from ajax call from server

How to get current user timezone in c#

I am building an application in MVC3 and when a user comes into my site I want to know that user's timezone. I want to know how to do this in c# not in javaScript?
As has been mentioned, you need your client to tell your ASP.Net server details about which timezone they're in.
Here's an example.
I have an Angular controller, which loads a list of records from my SQL Server database in JSON format. The problem is, the DateTime values in these records are in the UTC timezone, and I want to show the user the date/times in their local timezone.
I determine the user's timezone (in minutes) using the JavaScript "getTimezoneOffset()" function, then append this value to the URL of the JSON service I'm trying to call:
$scope.loadSomeDatabaseRecords = function () {
var d = new Date()
var timezoneOffset = d.getTimezoneOffset();
return $http({
url: '/JSON/LoadSomeJSONRecords.aspx?timezoneOffset=' + timezoneOffset,
method: 'GET',
async: true,
cache: false,
headers: { 'Accept': 'application/json', 'Pragma': 'no-cache' }
}).success(function (data) {
$scope.listScheduleLog = data.Results;
});
}
In my ASP.Net code, I extract the timezoneOffset parameter...
int timezoneOffset = 0;
string timezoneStr = Request["timezoneOffset"];
if (!string.IsNullOrEmpty(timezoneStr))
int.TryParse(timezoneStr, out timezoneOffset);
LoadDatabaseRecords(timezoneOffset);
... and pass it to my function which loads the records from the database.
It's a bit messy as I want to call my C# FromUTCData function on each record from the database, but LINQ to SQL can't combine raw SQL with C# functions.
The solution is to read in the records first, then iterate through them, applying the timezone offset to the DateTime fields in each record.
public var LoadDatabaseRecords(int timezoneOffset)
{
MyDatabaseDataContext dc = new MyDatabaseDataContext();
List<MyDatabaseRecords> ListOfRecords = dc.MyDatabaseRecords.ToList();
var results = (from OneRecord in ListOfRecords
select new
{
ID = OneRecord.Log_ID,
Message = OneRecord.Log_Message,
StartTime = FromUTCData(OneRecord.Log_Start_Time, timezoneOffset),
EndTime = FromUTCData(OneRecord.Log_End_Time, timezoneOffset)
}).ToList();
return results;
}
public static DateTime? FromUTCData(DateTime? dt, int timezoneOffset)
{
// Convert a DateTime (which might be null) from UTC timezone
// into the user's timezone.
if (dt == null)
return null;
DateTime newDate = dt.Value - new TimeSpan(timezoneOffset / 60, timezoneOffset % 60, 0);
return newDate;
}
It works nicely though, and this code is really useful when writing a web service to display date/times to users in different parts of the world.
Right now, I'm writing this article at 11am Zurich time, but if you were reading it in Los Angeles, you'd see that I edited it at 2am (your local time). Using code like this, you can get your webpages to show date times that make sense to international users of your website.
Phew.
Hope this helps.
This isn't possible server side unless you assume it via the users ip address or get the user to set it in some form of a profile. You could get the clients time via javascript.
See here for the javacript solution: Getting the client's timezone in JavaScript
You will need to use both client-side and server-side technologies.
On the client side:
(pick one)
This works in most modern browsers:
Intl.DateTimeFormat().resolvedOptions().timeZone
There is also jsTimeZoneDetect's jstz.determine(), or Moment-Timezone's moment.tz.guess() function for older browsers, thought these libraries are generally only used in older applications.
The result from either will be an IANA time zone identifier, such as America/New_York. Send that result to the server by any means you like.
On the server side:
(pick one)
Using TimeZoneInfo (on. NET 6+ on any OS, or older on non-Windows systems only):
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
Using TimeZoneConverter (on any OS):
TimeZoneInfo tzi = TZConvert.GetTimeZoneInfo("America/New_York");
Using NodaTime (on any OS):
DateTimeZone tz = DateTimeZoneProviders.Tzdb["America/New_York"];
I got the same issue , Unfortunately there is no way for the server to know the client timezone .
If you want you can send client timezone as header while making ajax call .
In-case if you want more info on adding the header this post may help how to add header to request : How can I add a custom HTTP header to ajax request with js or jQuery?
new Date().getTimezoneOffset();//gets the timezone offset
If you don't want to add header every time , you can think of setting a cookie since cookie is sent with all httpRequest you can process the cookie to get client timezone on server side . But i don't prefer adding cookies , for the same reason they sent with all http requests.
Thanks.
For Dot Net version 3.5 and higher you can use :
TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow);
but for Dot Net lower than version 3.5 you can handle it manually via this way :
first, get Offset from the client and store it in the cookie
function setTimezoneCookie(){
var timezone_cookie = "timezoneoffset";
// if the timezone cookie does not exist create one.
if (!$.cookie(timezone_cookie)) {
// check if the browser supports cookie
var test_cookie = 'test cookie';
$.cookie(test_cookie, true);
// browser supports cookie
if ($.cookie(test_cookie)) {
// delete the test cookie
$.cookie(test_cookie, null);
// create a new cookie
$.cookie(timezone_cookie, new Date().getTimezoneOffset());
// re-load the page
location.reload();
}
}
// if the current timezone and the one stored in cookie are different
// then store the new timezone in the cookie and refresh the page.
else {
var storedOffset = parseInt($.cookie(timezone_cookie));
var currentOffset = new Date().getTimezoneOffset();
// user may have changed the timezone
if (storedOffset !== currentOffset) {
$.cookie(timezone_cookie, new Date().getTimezoneOffset());
location.reload();
}
}
}
after that you can use a cookie in backend code like that :
public static string ToClientTime(this DateTime dt)
{
// read the value from session
var timeOffSet = HttpContext.Current.Session["timezoneoffset"];
if (timeOffSet != null)
{
var offset = int.Parse(timeOffSet.ToString());
dt = dt.AddMinutes(-1 * offset);
return dt.ToString();
}
// if there is no offset in session return the datetime in server timezone
return dt.ToLocalTime().ToString();
}
I know the user asked about a non-javascript solution, but I wanted to post a javascript solution that I came up with. I found some js libraries (jsTimezoneDetect, momentjs), but their output was an IANA code, which didn't seem to help me with getting a TimeZoneInfo object in C#. I borrowed ideas from jsTimezoneDetect. In javascript, I get the BaseUtcOffset and the first day of DST and send to server. The server then converts this to a TimeZoneInfo object.
Right now I don't care if the client Time Zone is chosen as "Pacific Time (US)" or "Baja California" for example, as either will create the correct time conversions (I think). If I find multiple matches, I currently just pick the first found TimeZoneInfo match.
I can then convert my UTC dates from the database to local time:
DateTime clientDate = TimeZoneInfo.ConvertTimeFromUtc(utcDate, timeZoneInfo);
Javascript
// Time zone. Sets two form values:
// tzBaseUtcOffset: minutes from UTC (non-DST)
// tzDstDayOffset: number of days from 1/1/2016 until first day of DST ; 0 = no DST
var form = document.forms[0];
var janOffset = -new Date(2016, 0, 1).getTimezoneOffset(); // Jan
var julOffset = -new Date(2016, 6, 1).getTimezoneOffset(); // Jul
var baseUtcOffset = Math.min(janOffset, julOffset); // non DST offset (winter offset)
form.elements["tzBaseUtcOffset"].value = baseUtcOffset;
// Find first day of DST (from 1/1/2016)
var dstDayOffset = 0;
if (janOffset != julOffset) {
var startDay = janOffset > baseUtcOffset ? 180 : 0; // if southern hemisphere, start 180 days into year
for (var day = startDay; day < 365; day++) if (-new Date(2016, 0, day + 1, 12).getTimezoneOffset() > baseUtcOffset) { dstDayOffset = day; break; } // noon
}
form.elements["tzDstDayOffset"].value = dstDayOffset;
C#
private TimeZoneInfo GetTimeZoneInfo(int baseUtcOffset, int dstDayOffset) {
// Converts client/browser data to TimeZoneInfo
// baseUtcOffset: minutes from UTC (non-DST)
// dstDayOffset: number of days from 1/1/2016 until first day of DST ; 0 = no DST
// Returns first zone info that matches input, or server zone if none found
List<TimeZoneInfo> zoneInfoArray = new List<TimeZoneInfo>(); // hold multiple matches
TimeSpan timeSpan = new TimeSpan(baseUtcOffset / 60, baseUtcOffset % 60, 0);
bool supportsDst = dstDayOffset != 0;
foreach (TimeZoneInfo zoneInfo in TimeZoneInfo.GetSystemTimeZones()) {
if (zoneInfo.BaseUtcOffset.Equals(timeSpan) && zoneInfo.SupportsDaylightSavingTime == supportsDst) {
if (!supportsDst) zoneInfoArray.Add(zoneInfo);
else {
// Has DST. Find first day of DST and test for match with sent value. Day = day offset into year
int foundDay = 0;
DateTime janDate = new DateTime(2016, 1, 1, 12, 0, 0); // noon
int startDay = zoneInfo.IsDaylightSavingTime(janDate) ? 180 : 0; // if southern hemsphere, start 180 days into year
for (int day = startDay; day < 365; day++) if (zoneInfo.IsDaylightSavingTime(janDate.AddDays(day))) { foundDay = day; break; }
if (foundDay == dstDayOffset) zoneInfoArray.Add(zoneInfo);
}
}
}
if (zoneInfoArray.Count == 0) return TimeZoneInfo.Local;
else return zoneInfoArray[0];
}
You can get this information from client to server (any web API call)
var timezoneOffset = new Date().getTimezoneOffset();
With the help of timezoneoffset details you can achieve the same. Here in my case i converted UTC DateTime to my client local datetime in Server side.
DateTime clientDateTime = DateTime.UtcNow - new TimeSpan(timezoneOffset / 60, timezoneOffset % 60, 0);
Click for code example
Take a look at this asp.net c# solution
TimeZoneInfo mytzone = TimeZoneInfo.Local;
System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_TIMEZONE"] ;

inject UTC time into the page

I'm using several literals to inject the user's time onto the the page. The values in the HTML are the UTC times.
var TheDay = parseInt($('#UserDayToday').html(), 10);
var TheMonth = parseInt($('#UserMonthToday').html(), 10);
var TheYear = parseInt($('#UserYearToday').html(), 10);
var TheHours = parseInt($('#UserTimeStampHours').html(), 10);
var TheMinutes = parseInt($('#UserTimeStampMinutes').html(), 10);
Now I want to build a time stamp with that time so I tried this:
var TheDateToday = new Date();
TheDateToday.setUTCFullYear(TheYear, TheMonth, TheDay);
TheDateToday.setUTCHours(TheHours, TheMinutes, 0, 0);
alert(TheDateToday);
When the alert comes on, it gives me the time with his timezone shift added. How can I just have the the UTC time. I know I can get it from the browser but I want to get the UTC time built from the data sent from the server, not retrieved from the user's machine by the browser.
Thanks
You are displaying the date in local time. Use the toUTCString method instead of the implicit toString method:
alert(TheDateToday.toUTCString());

Categories

Resources