In the application am working on, We have an option for each user to select their own timezone and when displaying data for the particular user, we are fetching timezone opted by him and display accordingly. Now as per the answer mentioned here, which is really an awesome one, I went on implementing the mentioned options, i.e. conversion of date at model level, and I have done it as below:
NotificationViewModel.cs
public class NotificationViewModel
{
public string Text{ get; set; }
public DateTime Moment
{
get
{
return _Created;
}
set
{
_Created = Repository.GetUserTimeZoneDateTime(value);
}
}
private DateTime _Created { get; set; }
public string Icon { get; set; }
}
Repository.cs
GetUserTimeZoneDateTime has 2 overloads
public static DateTime GetUserTimeZoneDateTime(DateTime dTime)
{
using (var context = new EntityContext())
{
var tZone = context.tbl_usrs.AsNoTracking().FirstOrDefault(x => x.uname == HttpContext.Current.User.Identity.Name).preferred_timezone;
var tZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tZone);
return TimeZoneInfo.ConvertTimeFromUtc(dTime, tZoneInfo);
}
}
public static DateTime GetUserTimeZoneDateTime(EntityContext context, DateTime dTime)
{
var tZone = context.tbl_usrs.AsNoTracking().FirstOrDefault(x => x.uname == HttpContext.Current.User.Identity.Name).preferred_timezone;
var tZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(tZone);
return TimeZoneInfo.ConvertTimeFromUtc(dTime, tZoneInfo);
}
In the above case first overload will be called, but then, when called from model level, HttpContext.Current will be null and hence it fails.
In the 2nd approach, I tried, the timezone will be fetched from controller level.
NotificationViewModel.cs
public class NotificationViewModel
{
public string Text { get; set; }
public DateTime Moment { get; set; }
public string Icon { get; set; }
}
TestController.cs
using (var context = new EntityContext())
{
var localTime = Repository.GetUserTimeZoneDateTime(context, DateTime.UtcNow);
List<NotificationViewModel> model = new List<NotificationViewModel>();
int days = DateTime.UtcNow.DayOfWeek - DayOfWeek.Sunday;
DateTime weekStart = localTime.AddDays(-days);
DateTime weekEnd = weekStart.AddDays(6);
var p = context.tbl_prchs
.Where(x => x.c_date <= weekEnd && x.c_date >= weekStart)
.Select(x => new NotificationViewModel()
{
Icon = "fa fa-gbp",
Moment = Repository.GetUserTimeZoneDateTime(context,x.c_date),
Text = "Test notes",
}).ToList();
model.AddRange(p);
}
var localTime = Repository.GetUserTimeZoneDateTime(context, DateTime.UtcNow); fetches proper datetime according to the preferred user timezone. But then Moment= Repository.GetUserTimeZoneDateTime(context,x.c_date), inside linq expression throws error as below
LINQ to Entities does not recognize the method 'System.DateTime GetUserTimeZoneDateTime(Direct_Commercial_Van.Models.EntityDataModel.dcvEntities, System.DateTime)' method, and this method cannot be translated into a store expression.
which is expected. What else options I can try here to achieve this? or how in other ways I can handle timezone issue here?