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

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

问题描述

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

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

我们无法检测到当前最终用户的当地时间和时区操作就可以了.他们选择不同的文化,比如 sv-se,en-us, ta-In 即使他们从欧洲/伦敦时区访问..

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

问题是我们使用 DateTime.Now 来存储记录创建/更新日期等

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 :(

在研究了 SO 之后,我们决定将所有历史日期存储在数据库中作为 DateTime.UtcNow

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

问题:

2013 年 12 月 29 日下午 3:15 瑞典时间创建了一条记录.

 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.

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

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 ConvertUTCBasedOnCulture(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 = ConvertUTCBasedOnCulture(b.CreatedDateTime);
            viewModel.Add(model);
        }
        return View(viewModel);
    }

查看代码

   @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.

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

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

问题

如何为登录 INDIA/USA/Anywhere` 的用户显示相同的记录创建日期 2013 年 12 月 29 日下午 3:15?

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

到目前为止,我在 ConvertUTCBasedOnCulture 中的逻辑是基于用户登录的文化.这应该与文化无关,因为用户可以使用来自印度/美国的任何文化登录

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

数据库列

创建时间:SMALLDATETIME

更新:尝试的解决方案:

数据库列类型:DATETIMEOFFSET

用户界面

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

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) {
        }
    }
});

应用

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

然后调用

 model.AddedDateTime = WebAppHelper.GetCurrentUserLocalTime();

在视图中

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

在视图中它向用户显示本地时间,但是我希望看到 dd-MMM-yyyy CET/PST(2 小时前).

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

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

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.

示例: 2013 年 1 月 25 日 17:49 CST(6 小时/天/月前)回答 所以来自美国/印度的其他用户可以真正理解该记录是在距印度/美国当前时间 6 小时后创建的

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?

推荐答案

听起来您需要存储 DateTimeOffset 而不是 DateTime.您可以只将本地 DateTime 存储给创建值的用户,但这意味着您不能执行任何排序操作等.您不能只使用 DateTime.UtcNow,因为它不会存储任何内容来指示创建记录时用户的本地日期/时间.

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?"

服务器的托管应该是无关紧要的——你永远不应该使用服务器的时区.但是,您需要知道用户的适当 UTC 偏移量(或时区).这不能仅基于文化来完成 - 您需要在用户机器上使用 Javascript 来确定您感兴趣的时间(不一定是现在")的 UTC 偏移量.

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").

一旦您确定了如何存储该值,检索它就很简单 - 如果您已经存储了 UTC 瞬间和一个偏移量,您只需应用该偏移量,您就会返回到原始用户的本地时间.您还没有说明如何将值转换为文本,但它应该只是简单地退出 - 只需格式化值,您应该会得到原始的本地时间.

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.

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

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

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

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