Can You Determine Timezone from Request Variables?
Asked Answered
C

5

34

Is there a way to do your timezone offsets on the server side, by reading something in the request over http, instead of sending everything to the client and letting it deal with it?

Comport answered 3/12, 2008 at 19:50 Comment(0)
F
23

This is more complicated but I've had to resort to this scenario before because machine and user profile settings sometimes don't match your visitor's preferences. For example, a UK visitor accessing your site temporarily from an Australian server.

  1. Use a geolocation service (e.g MaxMind.com) as suggested by @balabaster, to get the zone matching their IP (Global.Session_Start is best). This is a good match for local ISPs, but not so good for AOL. Store the offset from this in a session cookie.

  2. Or use JavaScript to get the time zone offset as part of a form submission/redirect when the user enters the site. This is the browser's current offset, but not necessarily the visitor's preferred zone. Use this value as a default; store in another session cookie.

    
    <script type="text/javascript" language="JavaScript">
    var offset = new Date();
    document.write('<input type="hidden" id="clientTzOffset" name="clientTzOffset" value="' + offset.getTimezoneOffset() + '"/>');
    </script>
    
  3. Allow the visitor to update the zone via a persistent cookie (for anonymous users) and a field in their account profile (if authenticated).

The persistent value #3 from overrides the session values. You can also store the same persistent cookie for authenticated users for displaying times before they login.

Feoff answered 23/12, 2008 at 5:7 Comment(0)
S
0

In any of the events prior to Page Unload...Request.ServerVariables. If you want their physical timezone then you check their IP address and use an IP to Geo-Location conversion tool.

I'm not sure if there's another way you can do it, so if you require the timezone their computer is configured for, it would have to wait for the page load for a javascript...

Sanskrit answered 3/12, 2008 at 19:55 Comment(3)
Thank you for creating hte longest version of No I have heard today.Comport
I used to wonder why I got localized ads for Oslo, Norway each time I surfed the net with Opera Mini on my phone, before I realized it's caused by IP to geographical location conversion... It just happens that Oslo is a couple of time zones away from where I live :-)Semicircle
ChanChan: You can always count on me for that ;)Sanskrit
H
0

We can get the time zone using the below code in server side instead of sending value from client.

private TimeZoneInfo GetRequestTimeZone()
    {
        TimeZoneInfo timeZoneInfo = null;
        DateTimeOffset localDateOffset;
        try
        {
            localDateOffset = new DateTimeOffset(Request.RequestContext.HttpContext.Timestamp, Request.RequestContext.HttpContext.Timestamp - Request.RequestContext.HttpContext.Timestamp.ToUniversalTime());
            timeZoneInfo = (from x in TimeZoneInfo.GetSystemTimeZones()
                            where x.BaseUtcOffset == localDateOffset.Offset
                            select x).FirstOrDefault();
        }
        catch (Exception)
        {
        }
        return timeZoneInfo;
    }

Thanks...

Handout answered 4/12, 2014 at 8:56 Comment(3)
Have you tried this on a server set to UTC and a client set to your actual timezone.Comport
You intrigued me enough to waste a few minutes of my time testing this, but sorry. Go Fish. Interesting concept. If the browsers would just send their local time with the request headers by default.Jhelum
This appears to merely be a roundabout way to determine the server's timezone, which can be accomplished much more simply.Sharitasharity
M
0

Is there a way to do your timezone offsets on the server side, by reading something in the request over http, instead of sending everything to the client and letting it deal with it?

Here's the solution I came up with, when I had the same issue with WCF web services:

How to get a WCF Web Service to return DateTimes in user's local timezone

Basically, I get my JavaScript/Angular code to determine the user's timezone, then pass this value to one of my WCF web services.

Notice how I have a web service called getListOfRecords which takes one parameter, the timezone-offset value.

$scope.loadSomeDatabaseRecords = function () {

    var d = new Date()
    var timezoneOffset = d.getTimezoneOffset();

    return $http({
        url: 'http://localhost:15021/Service1.svc/getListOfRecords/' + timezoneOffset,
        method: 'GET',
        async: true,
        cache: false,
        headers: { 'Accept': 'application/json', 'Pragma': 'no-cache' }
    }).success(function (data) {
        $scope.listScheduleLog = data.Results;
    });
}

From there, my C# code reads in the database records, applies that timezone offset to the UTC DateTime values, and returns it to the client.

Myer answered 5/8, 2016 at 9:19 Comment(1)
I ran into another wrinkle to this, which complicates it further. how does this handle returning dates for next December in my timezone for Daylight Savings. If it just uses offset, then many timezones match, and most of them don't utilize Daylight Savings.Comport
M
0

Here how I solved it using javascript and MVC:

First of all, on the main site script, I added the following code:

var clientOffset = getCookie("_clientOffset");
var currentOffset = new Date().getTimezoneOffset() * -1;
var reloadForCookieRefresh = false;

if (clientOffset  == undefined || clientOffset == null || clientOffset != currentOffset) {
    setCookie("_clientOffset", currentOffset, 30);
    reloadForCookieRefresh = true;
}

if (reloadForCookieRefresh)
    window.location.reload();

function setCookie(name, value, days) {
    var expires = "";
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = "; expires=" + date.toUTCString();
    }
    document.cookie = name + "=" + (value || "") + expires + "; path=/";
}

function getCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
    }
    return null;
}

And on the server side inside the action filter:

public class SetCurrentRequestDataFilter : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext context)
    {
        // currentRequestService is registered by request using IoC container
        var currentRequestService = iocResolver.Resolve<ICurrentRequestService>();

        if (context.HttpContext.Request.Cookies.AllKeys.Contains("_clientOffset"))
        {
            currentRequestService.ClientOffset = int.Parse(context.HttpContext.Request.Cookies.Get("_clientOffset").Value);
        }

    }
}
Maurinemaurise answered 8/9, 2020 at 9:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.