【问题标题】:Is timestamp (with different timezone formats) in future?未来是时间戳(具有不同时区格式)吗?
【发布时间】:2014-07-28 19:27:13
【问题描述】:

给我的时间戳格式如下:

2014 年 7 月 28 日星期一 11:39:29 GMT-05:00
2014 年 7 月 28 日星期一 13:39:29 GMT+02:00
2014 年 7 月 17 日星期四 00:02:02 UTC
2014 年 7 月 18 日星期五 14:47:01 UTC

如果结果在未来,我需要添加 X 分钟并返回真/假。诀窍是时间戳可以在任何时区,时区可以表示为 UTC 或 GMT(见上面的例子)。

这是我目前写的代码,但我不知道如何继续:

function isFuture($dateTimeStr, $minToAdd) {    
  $date1 = DateTime::createFromFormat("D M d H:i:s P Y", $dateTimeStr);

  // Something like $date1->date_interval_create_from_date_string('30 minutes);
  $date1->add(date_interval_create_from_date_string($minToAdd . ' minutes'));

  $now = new DateTime("now");
  return $date1 > $now;
}

echo isFuture("Mon Jul 28 14:39:29 GMT-05:00 2014", 30) ? "Future" : "Past";
echo isFuture("Fri Jul 18 14:47:01 UTC 2014", 30) ? "Future" : "Past";

回答我自己的问题

function isFuture($dateTimeStr, $minToAdd) {    
  $t = strtotime($dateTimeStr) + ($minToAdd*60);
  return $t > time();
}

【问题讨论】:

    标签: php date datetime timestamp


    【解决方案1】:

    只需使用DateTime::getTimezone() 获取$date1 的工作时区并将其用于您的$now DateTime 对象:

    function isFuture($dateTimeStr, $minToAdd) {    
      $date1 = DateTime::createFromFormat("D M d H:i:s P Y", $dateTimeStr);
    
      // Something like $date1->date_interval_create_from_date_string('30 minutes);
      $date1->add(date_interval_create_from_date_string($minToAdd . ' minutes'));
    
      $now = new DateTime("now", new DateTimeZone($date1->getTimezone()));
      return $date1 > $now;
    }
    

    这将适用于任何时区。但是,如果时区始终是 GMT/UTC,您可以将其硬编码到您的函数中:

    $now = new DateTime("now", new DateTimeZone('GMT'));
    

    【讨论】:

    • 即使在纠正了您遇到的一个错误之后,它也不能提供正确的结果:function isFuture($dateTimeStr, $minToAdd) { $date1 = DateTime::createFromFormat("D M d H:i:s P Y", $dateTimeStr); // Something like $date1->date_interval_create_from_date_string('30 minutes); $date1->add(date_interval_create_from_date_string($minToAdd . ' minutes')); $now = new DateTime("now", $date1->getTimezone()); return $date1 > $now; } echo isFuture("Mon Jul 28 14:39:29 GMT-12:00 2014", 30) ? "Future" : "Past";
    • 你能详细说明一下吗?在不知道它是如何工作的情况下很难改进答案。
    • 对于格式问题,我深表歉意。我还在学习 stackoverflow 语法;看起来在评论中将某些内容标记为代码与在原始帖子中将其标记为代码不同。当我的意思是它没有提供正确的结果时:过去的一些时间戳被报告为未来的。我最后给出的是一个例子:Mon Jul 28 14:39:29 GMT-12:00 2014
    • 不用担心。乍一看,我发现您在设置今天的日期时缺少new DateTimeZone() 部分。看看更正是否可以解决您的问题。
    • 嗯,这就是我提到的错误。您发布的原始代码 $now = new DateTime("now", new DateTimeZone($date1->getTimezone())) 给出了这个错误:DateTimeZone::__construct() expects parameter 1 to be string, object given。这就是为什么我把它改成$now = new DateTime("now", $date1->getTimezone())
    【解决方案2】:

    java.time

    Java 早期版本中麻烦的旧日期时间类和 Joda-Time 库现在都是遗留的,被 java.time 类所取代。

    格式化模式

    DateTimeFormatter 的格式化模式代码与旧的 SimpleDateFormat 类相似,但不相同。研究 JavaDoc。

    OffsetDateTime

    GMT-05:00 类型的项目是与 UTC 的偏移量,因此我们将其处理为 OffsetDateTime。您可以解析为ZonedDateTime,以便将这些对象与其他输入产生的对象混合在一起,但这会误导阅读您的代码的人。

    ZonedDateTime

    UTC实际上是一个时区的名称,所以我们处理为ZonedDateTime

    需要明确的是,GMTUTC 在传统商业应用程序方面实际上是相同的。但是这里的用法不同。加号或减号表示与 UTC 的偏移量,但不是完整的时区。 UTC 文本单独是一个区域名称,一个恰好是零偏移量的特定区域,但某种字符串也可以有一个区域名称 America/MontrealEurope/Paris

    查看时刻的不同方式的类:

    示例代码

    List<CharSequence> inputs = new ArrayList<> ( 4 );
    
    inputs.add ( "Mon Jul 28 11:39:29 GMT-05:00 2014" );
    inputs.add ( "Mon Jul 28 13:39:29 GMT+02:00 2014" );
    inputs.add ( "Thu Jul 17 00:02:02 UTC 2014" );
    inputs.add ( "Fri Jul 18 14:47:01 UTC 2014" );
    inputs.add ( "garbage-in garbaage-out" );
    inputs.add ( "Fri Jan 23 12:34:56 UTC 2099" );  // Future.
    
    Instant now = Instant.now ();  // Capture the current moment in UTC.
    
    DateTimeFormatter fGMT = DateTimeFormatter.ofPattern ( "EEE MMM dd HH:mm:ss OOOO uuuu" );
    DateTimeFormatter fUTC = DateTimeFormatter.ofPattern ( "EEE MMM dd HH:mm:ss z uuuu" );
    
    for ( CharSequence input : inputs ) {
        if ( input.length () == "Mon Jul 28 11:39:29 GMT-05:00 2014".length () ) {
            OffsetDateTime odt = OffsetDateTime.parse ( input , fGMT );
            if ( odt.toInstant ().isAfter ( now ) ) {
                System.out.println ( "input: " + input + " is future." );
            } else {
                System.out.println ( "input: " + input + " is past or present." );
            }
        } else if ( input.length () == "Thu Jul 17 00:02:02 UTC 2014".length () ) {
            ZonedDateTime zdt = ZonedDateTime.parse ( input , fUTC );
            if ( zdt.toInstant ().isAfter ( now ) ) {
                System.out.println ( "input: " + input + " is future." );
            } else {
                System.out.println ( "input: " + input + " is past or present." );
            }
        } else {
            System.err.println ( "ERROR - Unexpected input: " + input );
        }
    }
    

    输入:2014 年 7 月 28 日星期一 11:39:29 GMT-05:00 是过去还是现在。

    输入:2014 年 7 月 28 日星期一 13:39:29 GMT+02:00 过去或现在。

    输入:Thu Jul 17 00:02:02 UTC 2014 过去或现在。

    输入:过去或现在是 2014 年 7 月 18 日星期五 14:47:01 UTC。

    输入:1 月 23 日星期五 12:34:56 UTC 2099 是未来。

    this code run live at IdeOne.com

    日期时间数学

    增加时间似乎会分散您对问题核心问题的注意力。所以我在上面的例子中忽略了这个话题。

    但做起来很简单。上面的类有plus…minus… 方法,用于加减小时数、分钟数等。

    OffsetDateTime odtLater = odt.plusHours( 1 );
    ZonedDateTime zdtLater = zdt.plusMinutes( 90 );
    

    您可以将一段时间定义为Duration

    Duration d = Duration.ofMinutes( 90 ) ;
    ZonedDateTime zdtLater = zdt.plus( d );
    

    java.time 类使用immutable objects。因此,操作的结果是一个新对象,其值基于原始对象。


    关于java.time

    java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

    Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

      猜你喜欢
      • 2020-09-25
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 2012-02-04
      • 1970-01-01
      • 2020-03-17
      • 1970-01-01
      相关资源
      最近更新 更多