DateTime.Now和文化/时区具体 [英] DateTime.Now and Culture/Timezone specific

查看:563
本文介绍了DateTime.Now和文化/时区具体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的应用程序旨在处理来自不同地理位置的用户。


我们无法检测当前最终用户本地时间和
时区在其上操作。他们选择不同的文化,如sv-se,
en-us,ta-In即使他们从欧洲/伦敦时区访问。




我们将其托管在美国的托管服务器中,应用程序用户来自挪威/丹麦/瑞典/英国/美国/印度



我们使用 DateTime.Now 存储创建/更新日期等的问题。



由于 服务器在美国运行 ,所有用户数据都保存为美国时间:(



经过研究在SO中,我们决定将DB中的所有历史日期存储为 DateTime.UtcNow



PROBLEM: / strong>





上创建的记录2013年12月29日,瑞典时间3:15瑞典时间

  public ActionResult保存(BookingViewModel模型)
{
预订=新预订();
booki ng.BookingDateTime = model.BookingDateTime; // 10 Jan 2014 2:00 P.M
booking.Name = model.Name;
booking.CurrentUserId =(User)Session [currentUser]。UserId;
//美国服务器运行在太平洋时区,UTC-08:00
booking.CreatedDateTime = DateTime.UtcNow; // 2013年12月29日,6:15 A.M
BookingRepository.Save(booking);
return View(Index);
}

我们希望向登录印度的用户显示相同的历史记录时间/瑞典/美国。



截至目前,我们正在使用当前的文化用户登录,并从配置文件中选择时区,并使用TimeZoneInfo类进行转换

 < appSettings> 
< add key =sv-sevalue =W。欧洲标准时间/>
< add key =ta-INvalue =印度标准时间/>
< / appSettings>

private DateTime ConvertUTCBasedOnCuture(DateTime utcTime)
{
// utcTime是2013年12月29日,6:15 AM
string TimezoneId =
System.Configuration .ConfigurationManager.AppSettings
[System.Threading.Thread.CurrentThread.CurrentCulture.Name];
//如果用户将文化从sv-se更改为ta-IN,则显示不同的日期
TimeZoneInfo tZone = TimeZoneInfo.FindSystemTimeZoneById(TimezoneId);

返回TimeZoneInfo.ConvertTimeFromUtc(utcTime,tZone);
}
public ActionResult ViewHistory()
{
列表<预订> booking = new List< Booking>();
reservations = BookingRepository.GetBookingHistory();
列表< BookingViewModel> viewModel = new List< BookingViewModel>();
foreach(预订b)
{
BookingViewModel model = new BookingViewModel();
model.CreatedTime = ConvertUTCBasedOnCuture(b.CreatedDateTime);
viewModel.Add(model);
}
return View(viewModel);
}

查看代码

  @ Model.CreatedTime.ToString(dd-MMM-yyyy  -  HH':​​'mm)

注意:用户可以在登录之前更改文化/语言。它是一个基于本地化的应用程序,在美国服务器上运行



我看过 NODATIME ,但我不明白如何帮助托管在不同位置的多文化网络应用程序。



问题



如何显示相同的记录创建日期 2013年12月29日,3:15 PM 为登录INDIA /美国/无处不在?



截至目前,我在 ConvertUTCBasedOnCuture 中的逻辑是基于用户登录的文化。这应该与文化无关,因为用户可以使用印度/美国的任何文化登录



数据库列



创建时间: SMALLDATETIME



更新: / em>



数据库列类型:DATETIMEOFFSET



UI



最后,我在每个请求中使用以下Momento.js代码发送当前用户的本地时间

  $。ajaxSetup({
beforeSend:function(jqXHR,settings){
try {
/ /moment.format给出当前用户的日期,如2014-01-04T18:27:59 + 01:00
jqXHR.setRequestHeader('BrowserLocalTime',moment()。format());
}
catch(e){
}
}
});

申请

  public static DateTimeOffset GetCurrentUserLocalTime()
{
try
{
return
DateTimeOffset.Parse(HttpContext.Current.Request .Headers [BrowserLocalTime]);
}
catch
{
return DateTimeOffset.Now;
}
}

然后在

  model.AddedDateTime = WebAppHelper.GetCurrentUserLocalTime(); 

在视图中

 code> @ Model.AddedDateTime.Value.LocalDateTime.ToString(dd-MMM-yyyy  -  HH':​​'mm)

看来,它显示了当地的时间给用户,但是我想看到像 dd-MMM-yyyy CET / PST (2小时前)。



这个2小时前应该从最终用户的当地时间计算。完全一样的堆栈溢出问题创建/编辑时间与时区显示和本地用户计算。



示例: 25 '13 17:49 CST(6小时/天/月前)所以从美国/印度的用户来的另一个观看真的可以理解这个记录是从INDIA / USA当前时间恰好6个小时/ p>

几乎我认为我取得了一切,除了显示格式和计算。我该怎么办?

解决方案

这听起来像您需要存储一个 DateTimeOffset 而不是 DateTime 。您可以将本地 DateTime 存储到创建该值的用户,但这意味着您无法执行任何订购操作等。您可以' t只需使用 DateTime.UtcNow ,因为创建记录时不会存储任何指示用户本地日期/时间的内容。



或者,您可以随时随地存储用户的时区 - 这很难实现,但会为您提供更多信息,因此您可以说什么是用户本地时间一小时后?



服务器的主机应该是无关紧要的 - 你不应该使用服务器的时区。但是,您将需要知道用户适当的UTC偏移量(或时区)。这种不能仅仅根据文化来完成 - 您将需要在用户的机器上使用Javascript来确定您感兴趣的UTC偏移量(不一定是now)。



一旦你找出了如何存储值,检索它很简单 - 如果你已经存储了UTC时间和一个偏移量,你只需应用这个偏移量你会回到原来用户的当地时间。你没有说出你如何将价值观转化为文字,但它应该只是简单地退出 - 只是格式化价值,你应该得到原来的当地时间。



如果您决定使用Noda Time,您只需使用 OffsetDateTime 而不是 DateTimeOffset


Our application was designed to handle user from different Geographic location.

We are unable to detect what is the current end user local time and time zone operate on it. They select different culture like sv-se, en-us, ta-In even they access from Europe/London timezone..

We hosted it in a hosting server in US, application users are from Norway/Denmark/Sweden/UK/USA/India

The problem is we used DateTime.Now to store the record created/updated date, etc.

Since the Server runs in USA all user data are saved as US time :(

After researching in SO, we decided to stored all history dates in DB as DateTime.UtcNow

PROBLEM:

There is a record created on 29 Dec 2013, 3:15 P.M Swedish time.

 public ActionResult Save(BookingViewModel model)
    {
        Booking booking = new Booking();
        booking.BookingDateTime = model.BookingDateTime; //10 Jan 2014 2:00 P.M
        booking.Name = model.Name;
        booking.CurrentUserId = (User)Session["currentUser"].UserId;
        //USA Server runs in Pacific Time Zone, UTC-08:00
        booking.CreatedDateTime = DateTime.UtcNow; //29 Dec 2013, 6:15 A.M
        BookingRepository.Save(booking);
        return View("Index");
    }

We want to show the same history time to the user who logged in in India/Sweden/USA.

As of now we are using current culture user logged in and choose the timezone from a config file and using for conversion with TimeZoneInfo class

<appSettings>
    <add key="sv-se" value="W. Europe Standard Time" />
    <add key="ta-IN" value="India Standard Time" />
</appSettings>

    private DateTime ConvertUTCBasedOnCuture(DateTime utcTime)
    {
        //utcTime is 29 Dec 2013, 6:15 A.M
        string TimezoneId =                  
                System.Configuration.ConfigurationManager.AppSettings
                [System.Threading.Thread.CurrentThread.CurrentCulture.Name];
        // if the user changes culture from sv-se to ta-IN, different date is shown
        TimeZoneInfo tZone = TimeZoneInfo.FindSystemTimeZoneById(TimezoneId);

        return TimeZoneInfo.ConvertTimeFromUtc(utcTime, tZone);
    }
    public ActionResult ViewHistory()
    {
        List<Booking> bookings = new List<Booking>();
        bookings=BookingRepository.GetBookingHistory();
        List<BookingViewModel> viewModel = new List<BookingViewModel>();
        foreach (Booking b in bookings)
        {
            BookingViewModel model = new BookingViewModel();
            model.CreatedTime = ConvertUTCBasedOnCuture(b.CreatedDateTime);
            viewModel.Add(model);
        }
        return View(viewModel);
    }

View Code

   @Model.CreatedTime.ToString("dd-MMM-yyyy - HH':'mm")

NOTE: The user can change the culture/language before they login. Its a localization based application, running in US server.

I have seen NODATIME, but I could not understand how it can help with multi culture web application hosted in different location.

Question

How can I show a same record creation date 29 Dec 2013, 3:15 P.M for the users logged in INDIA/USA/Anywhere`?

As of now my logic in ConvertUTCBasedOnCuture is based user logged in culture. This should be irrespective of culture, since user can login using any culture from India/USA

DATABASE COLUMN

CreatedTime: SMALLDATETIME

UPDATE: ATTEMPTED SOLUTION:

DATABASE COLUMN TYPE: DATETIMEOFFSET

UI

Finally I am sending the current user's local time using the below Momento.js code in each request

$.ajaxSetup({
    beforeSend: function (jqXHR, settings) {
        try {
      //moment.format gives current user date like 2014-01-04T18:27:59+01:00
            jqXHR.setRequestHeader('BrowserLocalTime', moment().format());
        }
        catch (e) {
        }
    }
});

APPLICATION

public static DateTimeOffset GetCurrentUserLocalTime()
{
    try
    {
      return 
      DateTimeOffset.Parse(HttpContext.Current.Request.Headers["BrowserLocalTime"]);
    }
    catch
    {
        return DateTimeOffset.Now;
    }
}

then called in

 model.AddedDateTime = WebAppHelper.GetCurrentUserLocalTime();

In View

@Model.AddedDateTime.Value.LocalDateTime.ToString("dd-MMM-yyyy - HH':'mm")

In view it shows the local time to user, however I want to see like dd-MMM-yyyy CET/PST (2 hours ago).

This 2 hours ago should calculate from end user's local time. Exactly same as stack overflow question created/edited time with Timezone display and local user calculation.

Example: answered Jan 25 '13 at 17:49 CST (6 hours/days/month ago) So the other viewing from USA/INDIA user can really understand this record was created exactly 6 hours from INDIA/USA current time

Almost I think I achieved everything, except the display format & calculation. How can i do this?

解决方案

It sounds like you need to store a DateTimeOffset instead of a DateTime. You could just store the local DateTime to the user creating the value, but that means you can't perform any ordering operations etc. You can't just use DateTime.UtcNow, as that won't store anything to indicate the local date/time of the user when the record was created.

Alternatively, you could store an instant in time along with the user's time zone - that's harder to achieve, but would give you more information as then you'd be able to say things like "What is the user's local time one hour later?"

The hosting of the server should be irrelevant - you should never use the server's time zone. However, you will need to know the appropriate UTC offset (or time zone) for the user. This cannot be done based on just the culture - you'll want to use Javascript on the user's machine to determine the UTC offset at the time you're interested in (not necessarily "now").

Once you've worked out how to store the value, retrieving it is simple - if you've already stored the UTC instant and an offset, you just apply that offset and you'll get back to the original user's local time. You haven't said how you're converting values to text, but it should just drop out simply - just format the value, and you should get the original local time.

If you decide to use Noda Time, you'd just use OffsetDateTime instead of DateTimeOffset.

这篇关于DateTime.Now和文化/时区具体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆