2011-11-19 77 views
27

Tôi đang xây dựng một ứng dụng bằng mvc3 và tôi muốn làm điều đó khi người dùng truy cập vào trang web của tôi tôi muốn biết rằng múi giờ của người dùng đó là . tôi muốn biết làm thế nào để làm điều này trong C# không có trong kịch bản java?Cách lấy múi giờ của người dùng hiện tại trong C#

+0

Bài viết liên quan: http://stackoverflow.com/questions/338482/can-you-determine-timezone-from-request-variables – adatapost

Trả lời

18

Đây không phải là phía máy chủ, trừ khi bạn giả sử nó qua địa chỉ IP của người dùng hoặc yêu cầu người dùng đặt nó ở một dạng hồ sơ nào đó. Bạn có thể nhận được thời gian của khách hàng thông qua javascript.

Xem ở đây cho các giải pháp javacript: Getting the client's timezone in JavaScript

6

Tôi có cùng một vấn đề, Thật không may không có cách nào cho máy chủ biết múi giờ của khách hàng. Nếu bạn muốn, bạn có thể gửi múi giờ của khách hàng làm tiêu đề trong khi thực hiện cuộc gọi ajax.

In-trường hợp nếu bạn muốn biết thêm về cách thêm tiêu đề bài này có thể giúp làm thế nào để thêm tiêu đề để yêu cầu: How can I add a custom HTTP header to ajax request with js or jQuery?

new Date().getTimezoneOffset();//gets the timezone offset 

Nếu bạn không muốn thêm tiêu đề mọi thời gian, bạn có thể nghĩ thiết lập cookie vì cookie được gửi đi với tất cả httpRequest, bạn có thể xử lý cookie để nhận múi giờ của khách hàng ở phía máy chủ. Nhưng tôi không thích thêm cookie, vì lý do tương tự mà chúng được gửi cùng với tất cả các yêu cầu http. Cảm ơn.

+1

Đặt múi giờ trong cookie là một lựa chọn tuyệt vời khi bạn không muốn sử dụng ajax yêu cầu điều này, cộng với bạn không phải sử dụng JavaScript để hiển thị một ngày, chỉ để thiết lập cookie. –

+0

@RuudLenders nhưng bạn cần javascript để đặt cookie một lần – edc65

13

Như đã đề cập, bạn cần khách hàng của bạn để cho chi tiết máy chủ ASP.Net của bạn về những múi giờ họ đang ở.

Dưới đây là một ví dụ.

Tôi có bộ điều khiển góc, tải danh sách các bản ghi từ cơ sở dữ liệu SQL Server của tôi ở định dạng JSON. Vấn đề là, các giá trị DateTime trong những bản ghi này nằm trong múi giờ UTC và tôi muốn hiển thị cho người dùng ngày/giờ trong múi giờ địa phương của họ.

tôi xác định múi giờ của người dùng (tính theo phút) bằng cách sử dụng JavaScript "getTimezoneOffset()" chức năng, sau đó nối giá trị này đến URL của dịch vụ JSON Tôi đang cố gắng để gọi:

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

Trong ASP của tôi. Mã net, tôi trích xuất thông số timezoneOffset ...

int timezoneOffset = 0; 

string timezoneStr = Request["timezoneOffset"]; 
if (!string.IsNullOrEmpty(timezoneStr)) 
    int.TryParse(timezoneStr, out timezoneOffset); 

LoadDatabaseRecords(timezoneOffset); 

... và chuyển đến hàm của tôi để tải bản ghi từ cơ sở dữ liệu.

Hơi lộn xộn khi tôi muốn gọi hàm C# FromUTCData trên mỗi bản ghi từ cơ sở dữ liệu, nhưng LINQ to SQL không thể kết hợp SQL thô với hàm C#.

Giải pháp là đọc trong hồ sơ trước, sau đó lặp lại qua chúng, áp dụng bù trừ múi giờ cho các trường DateTime trong mỗi bản ghi.

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

Mã này thực sự hữu ích khi viết dịch vụ web hiển thị ngày/giờ cho người dùng ở các nơi khác nhau trên thế giới.

Hiện tại, tôi đang viết bài này lúc 11 giờ sáng giờ Zurich, nhưng nếu bạn đang đọc ở Los Angeles, bạn sẽ thấy rằng tôi đã chỉnh sửa nó lúc 2 giờ sáng (giờ địa phương của bạn). Sử dụng mã như thế này, bạn có thể làm cho các trang web của mình hiển thị thời gian ngày phù hợp với người dùng quốc tế của trang web của bạn.

Phew.

Hy vọng điều này sẽ hữu ích.

+2

Cảm ơn bạn Mike. Tôi nhận ra rằng bạn có thể làm 'TimeSpan mới (0, timezoneOffset, 0)' và nó tính toán số giờ đúng cách. – lsibaja

+0

cho sự hiểu biết của tôi nó không hoạt động vì DST – Giedrius

+0

DST không quan trọng. JavaScript của bạn sẽ tính đến điều này khi bạn gọi "getTimezoneOffset()". Tất cả những điều quan trọng là, trên máy chủ, DateTimes là * luôn luôn * UTC dựa trên, và trên máy khách, chúng tôi đang chính xác đi qua bù đắp múi giờ. –

3

Tôi biết người dùng đã hỏi về giải pháp không phải là javascript, nhưng tôi muốn đăng một giải pháp javascript mà tôi đã đưa ra. Tôi tìm thấy một số thư viện js (jsTimezoneDetect, momentjs), nhưng đầu ra của chúng là một mã IANA, điều này dường như không giúp tôi nhận được đối tượng TimeZoneInfo trong C#. Tôi đã mượn ý tưởng từ jsTimezoneDetect. Trong javascript, tôi nhận được BaseUtcOffset và ngày đầu tiên của DST và gửi đến máy chủ. Máy chủ sau đó chuyển đổi nó thành đối tượng TimeZoneInfo.

Hiện tại, tôi không quan tâm liệu múi giờ của khách hàng có được chọn là "Giờ Thái Bình Dương" hay "Baja California" hay không. Nếu tôi tìm thấy nhiều kết quả phù hợp, tôi hiện chỉ chọn kết quả TimeZoneInfo đầu tiên được tìm thấy.

sau đó tôi có thể chuyển đổi ngày UTC tôi từ cơ sở dữ liệu thời gian cục bộ:

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]; 
    } 
0

Đối Dot Net phiên bản 3.5 trở lên, bạn có thể sử dụng:

TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow); 

nhưng đối với Dot Net Theo phiên bản 3.5 bạn có thể xử lý nó bằng tay thông qua cách này:

đầu tiên được offset từ khách hàng và lưu trữ nó trong cookie

function setTimezoneCookie(){ 

var timezone_cookie = "timezoneoffset"; 

// if the timezone cookie not exists 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(); 
    } 
} 

}

sau đó bạn có thể sử dụng cookie trong mã phụ trợ như sau:

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(); 
} 
-1
System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_TIMEZONE"] ; 
+2

Bạn có thể cung cấp tham chiếu đến thông tin này không? Đoạn mã không có bất kỳ bối cảnh nào không phải là rất có giá trị. – axlj

Các vấn đề liên quan