2012-03-09 26 views
18

私はCRMシステム内のカレンダーアプリケーションで作業しています。ユーザーは、カレンダーでイベントを入力したタイムスタンプを半角で半角で表示する必要がありますDBを使用して、そのタイムスロット内に既に何かが予約されているかどうかを判断します。unixタイムスタンプを一番近い30分に丸める方法は?

たとえば、1330518155 = 292 2012年16:22:35 GMT + 4 のタイムスタンプがあるので、1330516800と1330518600は16:00と16:30と等しい必要があります。

誰かがアイデアを持っているか、私が愚かな方法でカレンダーを開発しようとしていると思ったら教えてください!そのような仕事に時間と日付で多くの作業を含む私の最初の時間ので、任意のアドバイスをいただきありがとうございます!

+0

http://php.net/manual/en/function.strtotime.phpを手動で機能させてみると便利です。タイムスタンプから任意の時間を追加したり削除したりするのは非常に簡単です。 – Kamil

+0

これは時間と日付とは何が関係していますか?本当に四捨五入されていない簡単な数学 – miki

答えて

58

モジュロを使用してください。

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

モジュロ演算子は、除算の残りの部分を与えます。

+0

時間は秒より後になりますが、それは問題の一部に過ぎません。なぜなら、分が30以上の場合、タイムブラケットはH:30〜H + 1:00です。 –

+1

1800で割るので、前半30分の増分(1:00、1:30、2:00、2:30など)から秒を指定します。 1:30:01の場合、モジュロ演算は1を返し、$ prevは1:30になります。 1800秒を追加すると、$ nextは2:00に等しくなります。 同様に、1:29:59の場合、モジュロは1799になり、$ prevは1:00になります。再び、1800を追加すると、次の1時間30分になります。 – SenorAmor

+2

シンプルなことがあるので、物事を考えて、基本的な算術演算を行う関数を探してみてください。 – Ash

0

UNIXタイムスタンプは秒数なので、1800(秒数は30分)を引くと、結果が得られます。

+2

ですね。 – thescientist

+0

これは、時間の境界ではなく、30分前と30分後に検出されます。彼の例をもう一度見てください。 –

2

モジュロ演算子を使用できます。

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

うまくいけば、これは、コメントを追加し、私はより具体的な例を作るしようとするでしょうしてくださいいない場合は、正しい方向にあなたを指すのに十分です。

0

localtimemktimeの機能を使用します。

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

PHPには、DateTimeクラスとそれが提供するメソッドがあります。あなたは好きなときにこれらを使うことができますが、組み込みのdate()strtotime()の関数を使う方が簡単です。

はここに私のソリューションです:

// 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 

あり、この上で行うことができ、いくつかの改善点がありますが、それは基本的なコアです。

[編集:私の変数名を修正!]

[編集:私の恥ずかしさに、私はそれが正しくその日の最後の半時間を処理していないことに気づき、ので、私はこの答えを再訪しました。私はその問題を修正しました。 $dayは、タイムスタンプに1秒分の秒を追加することで修正されていることに注意してください。このようにすれば、PHPは関係なく、月境界、うるう年などを越えることを心配する必要はありません。

2

私は質問をはっきりと読みませんでしたが、このコードは2つの間の範囲を必要としない人のために、最も近い30分に丸めます。 SenorAmorのコードの一部を使用します。小道具と正しい質問に対する彼の気違いの優雅な解決策。

$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

あなたは現在の時刻を取得し、時間の丸め(ダウン)を適用する必要がある場合、私は次の操作を行います:

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

それとも、オフセットを追加することにより、切り上げ可能性があり、時間をエコーする以外に何かをする。 forループは12時間分の増分を表示します。私は最近のプロジェクトで上記を使用しました。

0

私の最高の仕事からは遠いですが、ここでは文字列または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

これはまた、(例えば、Asia/Kathmandu)GMTからのオフセット30分の倍数でないタイムゾーンを処理するなど、タイムゾーン情報をDateTimeInterfaceを使用して保つ溶液です。

/** 
* 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'); 
} 

あなたはかかわらず、最初のDateTimeオブジェクトを作成しておく必要があります - おそらく$dateTime = new DateTimeImmutable('@' . $timestamp)ようなもので。コンストラクタでタイムゾーンを設定することもできます。

関連する問題