在下周六之前获取毫秒数

Get milliseconds by next Saturday

我正在开发每周一次的活动,但我需要在下周六之前获得毫秒数(unix 时间戳)。我该怎么做?

1 创建日历

 Calendar calNow = Calendar.getInstance();

2 创建另一个日历,将其设置为午夜并逐日移动,直到您到达星期六

    Calendar calNextSat = Calendar.getInstance();
    calNextSat.set(Calendar.HOUR, 0);
    calNextSat.set(Calendar.MINUTE, 0);
    calNextSat.set(Calendar.SECOND, 0);
    while(calNextSat.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY){
        calNextSat.add(Calendar.DATE, 1);
    }

    System.out.println(calNextSat.getTimeInMillis() - calNow.getTimeInMillis());

如果已经是星期六,则处理该场景,您将得到 <=0 个结果

我会使用 Calendar 来获取当前星期几。你可以减去它,

public static int daysUntilSaturday(Date d) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(d);
    return 7 - cal.get(Calendar.DAY_OF_WEEK);
}

然后你可以执行简单的算术

/*
 * 1000 milliseconds in a second, 60 seconds in a minute, 60 minutes in
 * an hour, 24 hours in a day.
 */
final long millisecondsPerDay = 1000L * 60 * 60 * 24;
System.out.println((daysUntilSaturday(new Date()) * millisecondsPerDay)
        + System.currentTimeMillis());

I am developing a weekly event

使用毫秒进行这种日期时间跟踪可能会使您误入歧途。例如,由于夏令时 (DST) 和其他异常情况,一天并不总是 24 小时,因此一周并不总是 ( ( 1000L * 60 * 60 * 24 ) * 7 ) 毫秒长。

乔达时间或java.time

我建议学习如何使用复杂的日期时间库。在 Java 中,这意味着:

时区

时区对于确定日期和星期几至关重要。使用 proper time zone names,永远不要使用 3 或 4 个字母的代码。

获取下一星期几的示例代码

这是使用 Joda-Time 2.7 的示例代码。

获取您所在的时区desire/expect。如果在 UTC 中工作,请使用常量 DateTimeZone.UTC.

DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );

获取您需要的日期时间值。这里我用的是当前时刻。

DateTime dateTime = DateTime.now( zone );

指定您想要的未来星期几。请注意,Joda-Time 使用明智的 #1 作为一周的第一天,而不是 java.util.Calendar 中的从零开始的计数。根据国际规范和标准,一周的第一天是星期一(不是美国常见的星期日)。

int dayOfWeek = DateTimeConstants.SATURDAY;

withDayOfWeek 命令可能会及时返回。因此,我们使用 ternary operator (?:) 通过根据需要增加一周来确保我们及时前进。

DateTime future = ( dateTime.getDayOfWeek() < dayOfWeek )
        ? dateTime.withDayOfWeek( dayOfWeek )
        : dateTime.plusWeeks( 1 ).withDayOfWeek( dayOfWeek );

您可能希望将一天中的时间调整为一天中的第一刻,以强调当天的焦点,而不是一天中的特定时刻。

future = future.withTimeAtStartOfDay(); // Adjust time-of-day to first moment of the day to stress the focus on the entire day rather than a specific moment within the day. Or use `LocalDate` class.

转储到控制台。

System.out.println( "Next day # " + dayOfWeek + " after " + dateTime + " is " + future );

当运行。

Next day # 6 after 2015-04-18T16:03:36.146-04:00 is 2015-04-25T00:00:00.000-04:00

直到那时

上面的代码给了我们期望的未来时间点(下周六)。

如果您真正想要的只是从现在到现在之间的毫秒数,请在每个内部计数之间减去-epoch 以毫秒为单位。请注意,在以毫秒为单位跟踪时间时,使用 64 位 long 而不是 32 位 int

long elapsedMilliseconds = ( future.getMillis() - dateTime.getMillis() );

请注意,如果您是在 java.time 而不是 Joda-Time 中完成这项工作,请注意内部 java.time 使用 nanoseconds rather than milliseconds. You can find milliseconds-savvy methods as I recall. Or divide nanoseconds by a million (yes, million not thousand, as microseconds 介于两者之间。

您可能想要更智能地表示现在和那时之间的时间跨度。 Joad-Time 提供三种 类 以不同方式表示时间跨度:

  • Interval(时间线上的一对不动点)
  • Period(月数、天数、小时数等)
  • Duration(毫秒数)。

示例代码,同样是 Joda-Time 2.7。

Interval interval = new Interval( dateTime , future );
Period period = interval.toPeriod();

转储到控制台。

System.out.println( "interval: " + interval );
System.out.println( "period: " + period );

当运行.

interval: 2015-04-18T16:17:45.109-04:00/2015-04-25T00:00:00.000-04:00
period: P6DT7H42M14.891S

注意 Period 值默认使用的字符串表示格式。该格式是标准格式,是其术语中 ISO 8601, called a duration 的一部分。该格式为 PnYnMnDTnHnMnS,其中 P 标记开始,T 将日期部分与时间部分分开。

Joda-Time 和 java.time 在解析和生成日期时间值的字符串表示时都使用 ISO 8601 作为它们的默认值。