使用用户的时间在GridView中显示DateTime

时间:2010-04-28 19:26:12

标签: asp.net gridview timezone local

我有一个以UTC时间存储的DateTime,我希望在GridView控件中以本地时间显示给用户。如何将DateTime转换为用户的时间(而不是我服务器的本地时间)?这是我在GridView Columns集合中出现的当前字段:

<asp:BoundField DataField="RunTime" HeaderText="Run Time"
  SortExpression="RunTime" DataFormatString="{0:f}" />

5 个答案:

答案 0 :(得分:3)

您需要知道用户的时区 - 例如,您的网站所保存的个人资料或用户数据。或者,您可以尝试根据GeoIP数据进行猜测,尽管这可能是可疑的,因为用户可能没有在他们的计算机上使用该特定时区。

.NET不会自动知道用户在远程端使用的时间。

答案 1 :(得分:3)

您可以使用JavaScript查找用户的时区:

var userTime =(new Date().getTimezoneOffset()/60)*(-1);

然后,将其存储在隐藏字段中或作为参数传递。在你的页面中,你必须覆盖GridView的RowDataBound事件,找到时间并使用DateTime的转换方法进行转换。

编辑: 可能最安全的方法是让用户将他们的时区存储在配置文件中。这样,关闭JavaScript不会影响您的应用程序。

编辑: 服务器端代码

    static void Main()
    {            
        const string timeFmt = "{0,-30}{1:yyyy-MM-dd HH:mm}";
        DateTime dt = DateTime.Now.ToUniversalTime();
        for (int i = -12; i <= 12; i++)
        {
            DateTime converted = ConvertToLocalDateTime(dt, i);
            Console.WriteLine(timeFmt, "Offset: " + i , converted);
        }
        Console.ReadLine();
    }

    static DateTime ConvertToLocalDateTime(DateTime dateTime, int offset)
    {
         TimeZoneInfo destinationTimeZone = TimeZoneInfo.GetSystemTimeZones()
            .Where(x => x.BaseUtcOffset.Hours.Equals(offset)).FirstOrDefault();

        var rule = destinationTimeZone.GetAdjustmentRules().Where(x =>
            x.DateStart <= dateTime && dateTime <= x.DateEnd)
            .FirstOrDefault();

        TimeSpan baseOffset = TimeSpan.Zero;
        if(rule != null)
        {
            baseOffset -= destinationTimeZone.IsDaylightSavingTime(dateTime) ? 
                rule.DaylightDelta : TimeSpan.Zero;
        }

        DateTimeOffset dto = DateTimeOffset.Parse(dateTime.ToString());
        return new DateTime(TimeZoneInfo.ConvertTimeFromUtc(dateTime, destinationTimeZone).Ticks + baseOffset.Ticks);
    }

请参阅:http://msdn.microsoft.com/en-us/library/system.timezone(VS.90).aspx

答案 2 :(得分:3)

对于我的网站,我只是使用jQuery对时区HTTP处理程序执行AJAX请求,该处理程序将在会话中记录时区,然后我创建了一个使用此值的扩展方法“ToVisitorTime”。

在基本模板或页眉中:

<script type="text/javascript" src="/lib/js/jquery.js"></script>

<asp:Placeholder id="plcTimezoneScript" Visible="false" runat="server">
    <script type="text/javascript">
        function getVisitorTimezone()
        {
            // get visitor timezone offset
            var curDt = new Date();
            $.post("/ajax/TimezoneOffset.ashx", {
                offset: -(curDt.getTimezoneOffset()/60)
            });
        }

        $(getVisitorTimezone);
    </script>  
</asp:Placeholder>

然后在代码隐藏中抓住会话时隐藏它:

protected void Page_Load(object sender, EventArgs e)
{
    object sessOffset = Session["OFFSET"];

    if (sessOffset == null)
    {
        plcTimezoneScript.Visible = true;
    }
}

对于/ajax/TimezoneOffset.ashx处理程序:

using System;
using System.Web;
using System.Web.SessionState;

public class TimezoneOffset : IHttpHandler, IRequiresSessionState
{

    public void ProcessRequest (HttpContext context) {
        context.Response.ContentType = "text/plain";
        object sessOffset = context.Session["OFFSET"];

        if (context.Request.RequestType == "POST")
        {
            if (sessOffset == null)
            {
                string offset = context.Request.Form.Get("offset");
                int Offset = 0;

                if (!String.IsNullOrEmpty(offset) 
                    && Int32.TryParse(offset, out Offset))
                {
                    context.Session.Add("OFFSET", Offset);
                }
            }
        }
    }

    public bool IsReusable {
        get {
            return false;
        }
    }

}

然后是一个扩展方法来处理显示正确的时间(如果需要,返回DateTime对象以进行进一步处理)。请记住将其存储在静态类中:

    public static DateTime ToVisitorTime(this DateTime UtcDate)
{
    // use timezone offset, if set
    object TimezoneOffset = HttpContext.Current.Session["OFFSET"];

    if (TimezoneOffset != null)
    {
        int Offset = 0;

        if (Int32.TryParse(TimezoneOffset.ToString(), out Offset))
        {
            UtcDate = UtcDate.AddHours(Offset);
        }
        else
        {
            UtcDate = UtcDate.ToLocalTime();
        }
    }
    else
    {
        // well, at least show the local server time
        UtcDate = UtcDate.ToLocalTime();
    }

    return UtcDate;
}

这是从我尚未发布的教程中获取的,但应该做你需要的。一个缺点是在第一页加载时,没有任何东西会在正确的时间内。

您可能应该使用JS方法,考虑到这已经需要JS才能工作。我建议使用Datejs插件并使用一些jQuery自动替换utc日期。

答案 3 :(得分:2)

您最好的选择是存储用户对时区的偏好。您无法从浏览器信息中正确猜出时区。

这是一个快速教程,用于在Session中存储选定的时区,并创建一个快速控件,可以在每个页面上更新打印日期。

http://www.dotnet-friends.com/articles/asp/artinasp381efae4-87c8-41ae-9427-2ae75edd9594.aspx

答案 4 :(得分:0)

您可以使用 Intl.DateTimeFormat().resolvedOptions().timeZone(所有现代浏览器都支持)将时区名称发送到服务器,并在那里执行适当的时区转换。

对于这种常见的事情,我认为 ASP.NET 会有一种固有且干净的方法来做到这一点!