0

I have an offset from UTC stored in minutes: e.g -240

I'm trying to find the corresponding UNIX timestamp of midnight of the current day for this particular offset.

I found similar information in questions like this one: How do I get the UTC time of "midnight" for a given timezone?

However, I don't have the city name/timezone jurisdiction, just a minute offset. I think this should be fine since for my purposes I don't need to account for daylight savings, it can be off by an hour and still be fine.

Examples

Offset: -420

Midnight on 7/12/2014: 1405148400 (unix TS)

With UTC, I would have to first tell if it's the next day or same day as the TZ because it may have a different "last midnight".

Community
  • 1
  • 1
server_kitten
  • 386
  • 3
  • 13

3 Answers3

1

While this solution looks a little ugly it does do what I think you're asking for! This example uses -180 minutes as the offset.

date_default_timezone_set('UTC');

// Work out which day the time zone is in
$day = strtotime('-180 minutes');

// Strip of the time part of the day, to give UTC midnight on the correct day
$utcMidnight = strtotime('midnight', $day);

// Now apply the offset in reverse to give the zone's midnight
$zoneMidnight = strtotime('+180 minutes', $utcMidnight);
Dave Morrissey
  • 4,371
  • 1
  • 23
  • 31
0

You could use date_default_timezone_set to make all time-related functions acknowledge the shift. First thing to do is to convert those minutes into hours, since the UTC gap is 1 hour between n and n+1.

$hours = $minutes / 60;

I would also recommend that you check the minutes values first :

if($minutes % 60 == 0) // We're good.

Now, if you want to convert the UTC offset to a timezone, you can create your function :

<?php
function offsetToTimezone($offset){
    $timezones = array( 
        "-12" => "Pacific/Kwajalein", 
        "-11" => "Pacific/Samoa", 
        "-10" => "Pacific/Honolulu", 
        "-9" => "America/Juneau", 
        "-8" => "America/Los_Angeles", 
        "-7" => "America/Denver", 
        "-6" => "America/Mexico_City", 
        "-5" => "America/New_York", 
        "-4" => "America/Caracas", 
        "-3.5" => "America/St_Johns", 
        "-3" => "America/Argentina/Buenos_Aires", 
        "-2" => "Atlantic/Azores",
        "-1" => "Atlantic/Azores", 
        "0" => "Europe/London", 
        "1" => "Europe/Paris", 
        "2" => "Europe/Helsinki", 
        "3" => "Europe/Moscow", 
        "3.5" => "Asia/Tehran", 
        "4" => "Asia/Baku", 
        "4.5" => "Asia/Kabul", 
        "5" => "Asia/Karachi", 
        "5.5" => "Asia/Calcutta", 
        "6" => "Asia/Colombo", 
        "7" => "Asia/Bangkok", 
        "8" => "Asia/Singapore", 
        "9" => "Asia/Tokyo", 
        "9.5" => "Australia/Darwin", 
        "10" => "Pacific/Guam", 
        "11" => "Asia/Magadan", 
        "12" => "Asia/Kamchatka" 
    );

    return $timezones[$offset];
}
?>

... and use if for conversion :

date_default_timezone_set(offsetToTimezone($hours));

By the way, I suggest you have a look at this answer, which provides you with a more elegant way to achieve the work of offsetToTimezone.

Now that your script if configured on the correct timezone, just ask for a timestamp :

$timestamp = mktime(0, 0, 0);

If at some time, you need to reset to timezone to default, you might need date_default_timezone_get to save it :

$timezone = date_default_timezone_get();
// Change to another timezone based on your offset.
// Get your timestamp.
date_default_timezone_set($timezone);
Community
  • 1
  • 1
John WH Smith
  • 2,743
  • 1
  • 21
  • 31
  • 1
    A good answer but a couple of things are not accounted for - there are timezones that don't have a whole hour offset (some are 30 minutes or 45 minutes), and an offset can't be mapped to a city like this with any accuracy - the city will have DST rules that are different from others with the same standard offset. – Dave Morrissey Jul 13 '14 at 00:38
  • The TZ lookup was the only solution I could think of, but I was hoping I wouldn't have to go that route, by using an internal function. – server_kitten Jul 13 '14 at 00:39
  • I am afraid the lack of accuracy may come the language itself, and its timezones support : http://php.net/manual/en/timezones.php. The *Others* category may give you more convenient alternatives, yet most of them (not UTC) are deprecated. You may have to fallback to direct calculation (subtracting the offset yourself). – John WH Smith Jul 13 '14 at 00:41
  • The Etc/GMT+X options are the best bet because they don't have DST, but only for the 60 minute zones. – Dave Morrissey Jul 13 '14 at 00:48
0

I had to think through it quite a bit, but I think this was the solution I was looking for. Let me know if you think this algorithm is incorrect.

function getLastMidnightForOffset( $minuteOffset ) {
    $today = mktime( 0, 0, 0 );
    $tomorrow = $today + 86400;
    $yesterday = $today - 86400;
    $offset = $minuteOffset * 60;

    if ( time() + $offset >= $tomorrow ) {
        $localMidnight = $tomorrow - $offset;
    } elseif ( time() + $offset >= $today ) {
        $localMidnight = $today - $offset;
    } else {
        $localMidnight = $yesterday - $offset;
    }

    return $localMidnight;
}
server_kitten
  • 386
  • 3
  • 13