使用 sql.timestamp 检查新的一天

Checking for a new day using sql.timestamp

我正在使用一些遗留代码并迭代一些值,遗留代码正在使用 sql.timestamp 值检查新一天的开始:

public static final long MILLIS_PER_SECOND = 1000;
public static final long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND;
public static final long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE;
public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;

 if (entry.getPeriodEnd().getTime() % TimestampUtils.MILLIS_PER_DAY == 0 || i >= throughputEntries.size()) {

       ...
}

结果永远不会 0 所以它只会在 i >= throughputEntries.size()

时进入 if

我无法理解他是如何获得 0 结果的,可能他的数据不同并且总是以某个时间段结束,该时间段会产生 0

我可以重写代码,也许可以检查日期,但想知道他是如何用他的代码实现的。

我不确定我提供的代码是否可以解决这个问题,但也许我遗漏了什么...

编辑

所以我最终解决了这个问题,感谢@t0r0X 和@Leo

我修改了代码以使用 Joda-Time,如下所示:

 LocalDate newDay = null;
 int count = 0;


public void calcAvg(){

    DateTimeZone zone = DateTimeZone.getDefault();
    LocalDate throughtputDate = entry.getPeriodEnd().toDateTime(zone).toLocalDate();

    if ( this.newDay(throughtputDate) || i >= throughputEntries.size()) {

       ...
    }

}


public boolean newDay(LocalDate date){

    boolean go = false;
    if(count !=0){
        if(date.isAfter(newDay)){

            newDay = date;
            go = true;
        }
    }
    else{
        newDay = date;
        count++;
    }

    return go;
}

检查新日期的方法可能比我写的方法更简洁,但时间不等人。

原始代码的作者可能使用了合成的“圆形”数据。也许使用(现在已弃用)java.sql.Timestamp constructor ...

new Timestamp(116, 1, 25, 0, 0, 0, 0)

或者可能使用(也已弃用)Date constructor ...

new Timestamp(new Date(116, 1, 25).getTime())

或者他可能已经解析了一些测试数据,例如'2016-01-25'...

你看,没有毫秒! ;-)

无论如何,检查“新的一天”取决于您如何定义它。通常你需要一个参考日期,就像之前处理过的条目一样。

更新:

第 4 次查看代码 entry.getPeriodEnd().getTime():条目看起来像时间段...所以必须有一个 getPeriodBegin() 方法...我想需要的检查是验证如果经期结束在另一天而不是经期开始...我说得对吗?

脏代码(不推荐使用的方法):

Timestamp begin = entry.getPeriodBegin()
Timestamp end = entry.getPeriodEnd()
if (begin.getYear() != end.getYear() || begin.getMonth() != end.getMonth() || begin.getDay() != end.getDay() ....) 

干净的代码:
我的建议:甚至不要以 java.util.Calendar (proposal on Whosebug). Either use DateUtils from Apache Commons Lang (also suggested here on Whosebug; comments are relevant), or, my favourite, get JodaTime and stop worring (suggestion also on Whosebug; comments are relevant) 开头。我个人一直对 JodaTime 很满意。

PS

不要忘记(感谢@Leo 对这个问题的评论,我仍然生活,咳咳,工作,在一个 Java 6-7 的世界 :-/ ...):如果使用 Java 8 或更高版本,选择新的 java.time 类.

是正确的,但使用过时的 类。

此外,您通常不应使用 java.sql.* 类 来处理业务逻辑。它们旨在用于进出数据库的数据传输,仅此而已。立即将 java.sql.Timestamp/.Date/.Time 转换为 java.time 类型。使用 java.time 类型执行您的业务逻辑。希望有一天 java.sql 类型会在 JDBC 驱动程序更新为直接处理 java.time 后消失。

问题和评论不清楚。但我会尝试一下,因为它似乎与按日期累积数字有关。

java.time

Java8及以后自带的优秀java.time framework. See Tutorial。这些新的 类 取代了 java.util.Date/.Calendar.

的旧的麻烦 类

其中新的类是LocalDate for a date-only value without time-of-day nor time zone. The java.sql.Timestamp is a date-time value rather than date-only. But we can convert to java.time.Instant, a moment on the timeline in UTC. Then we apply a time zone (ZoneId) to get a ZonedDateTime. From that we may extract a LocalDate. That LocalDate is just what we need as keys for a Map累加一个数。

Instant instant = myJavaSqlTimestamp.toInstant();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
LocalDate localDate = zdt.toLocalDate();

请注意时区在这里很重要。虽然 LocalDate 不保留时区,但日期仅在时区上下文中有意义。在任何给定时刻,世界各地的日期都不相同。如果未指定,则应用 JVM 当前的默认时区。此页面上的其他代码明确要求当前默认值。我强烈建议不要在此问题中使用默认值。 JVM 的当前默认时区可以在应用程序运行之前随时更改,甚至可以在 您的应用程序运行时更改!如果按日期对数字进行总计,则业务逻辑必须为该日期的含义考虑一些时区。 Specify that time zone explicitly。这里我随意选择了America/Montreal.

之前,您可能会实例化一个 Map of LocalDate to a sum of the numbers being collected. I will assume we are dealing with BigInteger 作为我们此演示的数字类型。

Map< LocalDate , BigInteger ) map = new HashMap<>();

我们为遇到的每个 LocalDate 日期值在该地图中添加一个条目。我们假设我们有一个 BigInteger myNumber 通过 JDBC.

从数据库中获取
BigInteger oldTotalForDate = map.get( localDate );
BigInteger newTotalForDate = ( null == oldTotalForDate ) ? myNumber : oldTotalForDate.add( myNumber) ;
if ( null == newTotalForDate ) {  // If we failed to get new sum.
    // TODO: Handle error condition. Perhaps: map.remove(key);
} else {  // Else normal, we have a new total. Store it in map.
    map.put( localDate , newTotalForDate );  // Replaces any old value.
}

上述代码可以通过使用 Java 8 及更高版本中新的 Map::merge 方法使用新的 Lambda 语法功能来缩短。