2012-03-09 69 views
18

Ok vì vậy tôi đang làm việc trên một ứng dụng lịch trong hệ thống CRM của mình và tôi cần tìm giới hạn trên và dưới của nửa giờ surrorunding dấu thời gian mà ai đó đã nhập một sự kiện trong lịch để chạy một số SQL trên DB để xác định xem họ đã có thứ gì đó được đặt trong khoảng thời gian đó hay chưa.Làm thế nào để làm tròn dấu thời gian lên và xuống đến nửa giờ gần nhất?

Ví dụ: Tôi có dấu thời gian của 1330518155 = 29 tháng 2 năm 2012 16:22:35 GMT + 4 vì vậy tôi cần nhận 1330516800 và 1330518600 tương đương 16:00 và 16:30.

Nếu có ai có ý tưởng hoặc nghĩ rằng tôi đang tiếp cận phát triển lịch theo cách ngu ngốc, hãy cho tôi biết! Đây là lần đầu tiên tôi làm một công việc liên quan đến quá nhiều công việc với thời gian và ngày tháng nên mọi lời khuyên đều được đánh giá cao!

+0

cố gắng sử dụng chức năng trong thủ công - http://php.net/manual/en/function.strtotime.php - phải hữu ích, bạn có thể thêm hoặc xóa bất kỳ khoảng thời gian nào từ dấu thời gian rất dễ dàng. – Kamil

+0

điều này phải làm gì với thời gian và ngày? nó đơn giản toán học – miki

Trả lời

58

Sử dụng modulo.

$prev = 1330518155 - (1330518155 % 1800); 
$next = $prev + 1800; 

Toán tử modulo cung cấp phần còn lại của bộ phận.

+0

Điều đó sẽ tìm thấy giây kể từ giờ, nhưng đó chỉ là một phần của vấn đề, bởi vì nếu phút là> = 30, khung thời gian là H: 30 đến H + 1: 00 –

+1

Vì chúng ta chia cho 1800, nó sẽ cho giây kể từ khi tăng nửa giờ cuối cùng (1:00, 1:30, 2:00, 2:30, v.v ...). Nếu là 1:30:01, thao tác modulo sẽ trả về 1 và $ trước sẽ là 1:30. Thêm 1800 giây sẽ làm cho $ tiếp theo bằng 2:00. Tương tự, nếu là 1:29:59, modulo sẽ là 1799 và $ trước sẽ là 1:00. Một lần nữa, thêm 1800 sẽ làm cho $ 1 tới 1:30. – SenorAmor

+2

Vì vậy, đơn giản đôi khi bạn chỉ cần cố gắng để suy nghĩ về mọi thứ và tìm kiếm một chức năng để làm một số số học cơ bản! – Ash

0

Như bạn có thể đã biết, dấu thời gian UNIX là một số giây, vì vậy hãy trừ/thêm 1800 (số giây trong 30 phút) và bạn sẽ nhận được kết quả mong muốn.

+2

đó là không thực sự làm tròn mặc dù, là nó? – thescientist

+0

Điều đó sẽ tìm thấy 30 phút trước và 30 phút sau, không phải là "trên giờ" và "vào nửa giờ" giới hạn thời gian. Xin hãy xem lại ví dụ của anh ta. –

2

Bạn có thể sử dụng toán tử modulo.

$time -= $time % 3600; // nearest hour (always rounds down) 

Hy vọng điều này đủ để chỉ cho bạn đúng hướng, nếu không, vui lòng thêm nhận xét và tôi sẽ cố gắng tạo một ví dụ cụ thể hơn.

0

Tôi muốn sử dụng localtime và chức năng mktime.

$localtime = localtime($time, true); 
$localtime['tm_sec'] = 0; 
$localtime['tm_min'] = 30; 
$time = mktime($localtime); 
3

PHP không có lớp DateTime và toàn bộ các phương thức mà nó cung cấp. Bạn có thể sử dụng chúng nếu bạn thích, nhưng tôi thấy dễ dàng hơn khi sử dụng các hàm date()strtotime() được cài sẵn.

Đây là giải pháp của tôi:

// Assume $timestamp has the original timestamp, i.e. 2012-03-09 16:23:41 

$day = date('Y-m-d', $timestamp); // $day is now "2012-03-09" 
$hour = (int)date('H', $timestamp); // $hour is now (int)16 
$minute = (int)date('i', $timestamp); // $minute is now (int)23 

if($minute < 30){ 
    $windowStart = strtotime("$day $hour:00:00"); 
    $windowEnd = strtotime("$day $hour:30:00"); 
} else { 
    $windowStart = strtotime("$day $hour:30:00"); 
    if(++$hour > 23){ 
    // if we crossed midnight, fix the date and set the hour to 00 
    $day = date('Y-m-d', $timestamp + (24*60*60)); 
    $hour = '00'; 
    } 
    $windowEnd = strtotime("$day $hour:00:00"); 
} 

// Now $windowStart and $windowEnd are the unix timestamps of your endpoints 

Có một vài cải tiến mà có thể được thực hiện về vấn đề này, nhưng đó là cốt lõi cơ bản.

[Chỉnh sửa: chỉnh tên biến tôi]

[Edit: Tôi đã xem xét lại câu trả lời này bởi vì, để bối rối của tôi, tôi nhận ra rằng nó đã không xử lý cuối cùng nửa giờ của một ngày chính xác. Tôi đã khắc phục vấn đề đó. Lưu ý rằng $day được cố định bằng cách thêm giá trị ngày của một giây vào dấu thời gian - thực hiện theo cách này có nghĩa là chúng tôi không phải lo lắng về việc vượt qua ranh giới tháng, ngày nhuận, v.v. vì PHP sẽ định dạng chính xác cho chúng tôi bất kể.]

2

Tôi đã không đọc các câu hỏi một cách rõ ràng, nhưng mã này sẽ tròn trong nửa giờ gần nhất, đối với những người không cần phạm vi giữa hai người. Sử dụng một số mã của SenorAmor. Đạo cụ và giải pháp thanh lịch điên rồ của mình cho câu hỏi đúng.

$time = 1330518155; //Or whatever your time is in unix timestamp 

//Store how many seconds long our rounding interval is 
//1800 equals one half hour 
//Change this to whatever interval to round by 
$INTERVAL_SECONDS = 1800; //30*60 

//Find how far off the prior interval we are 
$offset = ($time % $INTERVAL_SECONDS); 

//Removing this offset takes us to the "round down" half hour 
$rounded = $time - $offset; 

//Now add the full interval if we should have rounded up 
if($offset > ($INTERVAL_SECONDS/2)){ 
    $nearestInterval = $rounded + $INTERVAL_SECONDS; 
} 
else{ 
    $nearestInterval = $rounded 
} 
1

Nếu bạn cần để có được thời gian hiện tại và sau đó áp dụng làm tròn (giảm) của thời điểm đó, tôi sẽ làm như sau:

$now = date('U'); 
$offset = ($now % 1800); 
$now = $now-$offset; 
for ($i = 0;$i < 24; $i++) 
{ 
    echo date('g:i',$now); 
    $now += 1800; 
} 

Hoặc bạn có thể làm tròn lên bằng cách thêm bù đắp, và làm điều gì đó hơn là chỉ lặp lại thời gian. Vòng lặp for sau đó hiển thị 12 giờ gia tăng. Tôi đã sử dụng ở trên trong một dự án gần đây.

0

Xa công việc tốt nhất của tôi ... nhưng đây là một số chức năng để làm việc với chuỗi hoặc dấu thời gian unix.

/** 
* Takes a timestamp like "2016-10-01 17:59:01" and returns "2016-10-01 18:00" 
* Note: assumes timestamp is in UTC 
* 
* @param $timestampString - a valid string which will be converted to unix with time() 
* @param int $mins - interval to round to (ex: 15, 30, 60); 
* @param string $format - the format to return the timestamp default is Y-m-d H:i 
* @return bool|string 
*/ 
function roundTimeString($timestampString, $mins = 30, $format="Y-m-d H:i") { 
    return gmdate($format, roundTimeUnix(time($timestampString), $mins)); 
} 

/** 
* Rounds the time to the nearest minute interval, example: 15 would round times to 0, 15, 30,45 
* if $mins = 60, 1:00, 2:00 
* @param $unixTimestamp 
* @param int $mins 
* @return mixed 
*/ 
function roundTimeUnix($unixTimestamp, $mins = 30) { 
    $roundSecs = $mins*60; 
    $offset = $unixTimestamp % $roundSecs; 
    $prev = $unixTimestamp - $offset; 
    if($offset > $roundSecs/2) { 
     return $prev + $roundSecs; 
    } 
    return $prev; 
} 
0

Đây là một giải pháp sử dụng DateTimeInterface và bảo mật thông tin múi giờ vv cũng sẽ xử lý các múi giờ mà không phải là một bội số của 30 phút bù đắp từ giờ (ví dụ Asia/Kathmandu).

/** 
* Return a DateTimeInterface object that is rounded down to the nearest half hour. 
* @param \DateTimeInterface $dateTime 
* @return \DateTimeInterface 
* @throws \UnexpectedValueException if the $dateTime object is an unknown type 
*/ 
function roundToHalfHour(\DateTimeInterface $dateTime) 
{ 
    $hours = (int)$dateTime->format('H'); 
    $minutes = $dateTime->format('i'); 

    # Round down to the last half hour period 
    $minutes = $minutes >= 30 ? 30 : 0; 

    if ($dateTime instanceof \DateTimeImmutable) { 
     return $dateTime->setTime($hours, $minutes); 
    } elseif ($dateTime instanceof \DateTime) { 
     // Don't change the object that was passed in, but return a new object 
     $dateTime = clone $dateTime; 
     $dateTime->setTime($hours, $minutes); 
     return $dateTime; 
    } 
    throw new UnexpectedValueException('Unexpected DateTimeInterface object'); 
} 

Bạn cần phải tạo đối tượng DateTime trước tiên - có thể với một cái gì đó như $dateTime = new DateTimeImmutable('@' . $timestamp). Bạn cũng có thể đặt múi giờ trong hàm tạo.

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