php 如何将unix时间戳上下舍入到最接近的半小时?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9639642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to round unix timestamp up and down to nearest half hour?
提问by Ash
Ok so I am working on a calendar application within my CRM system and I need to find the upper and lower bounds of the half an hour surrorunding the timestamp at which somebody entered an event in the calendar in order to run some SQL on the DB to determine if they already have something booked in within that timeslot.
好的,所以我正在我的 CRM 系统中处理日历应用程序,我需要找到半小时的上限和下限,围绕某人在日历中输入事件的时间戳,以便在数据库上运行一些 SQL 以确定他们是否已经在该时间段内预订了一些东西。
For example I have the timestamp of 1330518155 = 29 February 2012 16:22:35 GMT+4 so I need to get 1330516800 and 1330518600 which equal 16:00 and 16:30.
例如,我的时间戳为 1330518155 = 2012 年 2 月 29 日 16:22:35 GMT+4,所以我需要得到 1330516800 和 1330518600,它们等于 16:00 和 16:30。
If anyone has any ideas or think I am approaching developing the calendar in a stupid way let me know! Its my first time on such a task involving so much work with times and dates so any advice appreciated!
如果有人有任何想法或认为我正在以一种愚蠢的方式开发日历,请告诉我!这是我第一次执行这样的任务,涉及这么多时间和日期的工作,所以任何建议都表示赞赏!
回答by SenorAmor
Use modulo.
使用模数。
$prev = 1330518155 - (1330518155 % 1800);
$next = $prev + 1800;
The modulo operator gives the remainder part of division.
模运算符给出除法的余数部分。
回答by Jazz
PHP does have a DateTime class and a whole slough of methods that it provides. You could use these if you like, but I find it easier to use the built-in date()
and strtotime()
functions.
PHP 确实有一个 DateTime 类和它提供的一整套方法。如果你愿意,你可以使用这些,但我发现使用内置date()
和strtotime()
函数更容易。
Here's my solution:
这是我的解决方案:
// 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
There are a few improvements that can be made on this, but that's the basic core.
可以对此进行一些改进,但这是基本核心。
[Edit: corrected my variable names!]
[编辑:更正了我的变量名!]
[Edit: I've revisited this answer because, to my embarrassment, I realized that it didn't handle the last half-hour of a day correctly. I've fixed that issue. Note that $day
is fixed by adding a day's worth of seconds to the timestamp -- doing it this way means we don't have to worry about crossing month boundaries, leap days, etc. because PHP will format it correctly for us regardless.]
[编辑:我重新审视了这个答案,因为令我尴尬的是,我意识到它没有正确处理一天的最后半小时。我已经解决了那个问题。请注意,这$day
是通过向时间戳添加一天的秒数来修复的——这样做意味着我们不必担心跨越月份边界、闰日等,因为无论如何 PHP 都会为我们正确格式化。]
回答by Eric G
I didn't read the questions clearly, but this code will round to the nearest half hour, for those who don't need the range between the two. Uses some of SenorAmor's code. Props and his mad elegant solution to the correct question.
我没有清楚地阅读问题,但是对于那些不需要两者之间范围的人,此代码将四舍五入到最接近的半小时。使用一些 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
}
回答by Chris Browne
You could use the modulo operator.
您可以使用模运算符。
$time -= $time % 3600; // nearest hour (always rounds down)
Hopefully this is enough to point you in the right direction, if not please add a comment and I'll try to craft a more specific example.
希望这足以为您指明正确的方向,如果没有,请添加评论,我将尝试制作一个更具体的示例。
回答by royjm
If you need to get the current time and then apply the rounding (down) of the time, I would do the following:
如果您需要获取当前时间然后应用时间的舍入(向下),我将执行以下操作:
$now = date('U');
$offset = ($now % 1800);
$now = $now-$offset;
for ($i = 0;$i < 24; $i++)
{
echo date('g:i',$now);
$now += 1800;
}
Or you could round up by adding the offset, and do something more than just echo the time. The for loop then displays the 12 hours of increments. I used the above in a recent project.
或者您可以通过添加偏移量来进行汇总,并做一些不仅仅是回显时间的事情。然后 for 循环显示 12 小时的增量。我在最近的一个项目中使用了上述内容。
回答by blak3r
Far from my best work... but here's some functions for working with string or unix time stamp.
远不是我最好的工作……但这里有一些用于处理字符串或 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;
}
回答by Dezza
This is a solution using DateTimeInterface
and keeping timezone information etc. Will also handle timezones that are not a multiple of 30 minutes offset from GMT (e.g. Asia/Kathmandu
).
这是使用DateTimeInterface
和保留时区信息等的解决方案。还将处理不是 GMT 偏移 30 分钟倍数的时区(例如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');
}
You'll need to have created the DateTime object first though - perhaps with something like $dateTime = new DateTimeImmutable('@' . $timestamp)
. You can also set the timezone in the constructor.
不过,您需要先创建 DateTime 对象 - 也许使用类似$dateTime = new DateTimeImmutable('@' . $timestamp)
. 您还可以在构造函数中设置时区。
回答by Vael Victus
Here's a more semantic method for those that have to make a few of these, perhaps at certain times of the day.
对于那些必须在一天中的某些时间制作其中一些的人来说,这是一种更具语义的方法。
$time = strtotime(date('Y-m-d H:00:00'));
You can change that H
to any 0-23 number, so you can round to that hour of that day.
您可以将其更改H
为任何 0-23 数字,这样您就可以四舍五入到当天的那个小时。
回答by Sylvain Defresne
I'd use the localtime
and the mktime
function.
我会使用localtime
和mktime
功能。
$localtime = localtime($time, true);
$localtime['tm_sec'] = 0;
$localtime['tm_min'] = 30;
$time = mktime($localtime);
回答by Pateman
As you probably know, a UNIX timestamp is a number of seconds, so substract/add 1800
(number of seconds in 30
minutes) and you will get the desired result.
您可能知道,UNIX 时间戳是秒数,因此减去/添加1800
(以30
分钟为单位的秒数),您将获得所需的结果。