获取两个日期之间的周数.

Ant*_*ith 21 java date jodatime

我在一个项目中工作,我在Date中有两种类型.我想计算这两个日期之间的周数.日期可能是不同的年份.对此有什么好的解决方案吗?

我试图用其他主题中提出的Joda-time来实现这一点.

我不熟悉这个库,但我尝试做这样的事情:

public static int getNumberOfWeeks(Date f, Date l){
    Calendar c1 = Calendar.getInstance();
    Calendar c2 = Calendar.getInstance();
    c1.setTime(f);
    c2.setTime(l);
    DateTime start = new DateTime(c1.YEAR, c1.MONTH, c1.DAY_OF_MONTH, 0, 0, 0, 0);
    DateTime end   = new DateTime(c2.YEAR, c2.MONTH, c2.DAY_OF_MONTH, 0, 0, 0, 0);
    Interval interval = new Interval(start, end);
    Period p = interval.toPeriod();
    return p.getWeeks();
}
Run Code Online (Sandbox Code Playgroud)

但这完全错了......有什么建议吗?

nan*_*sen 34

joda时间非常简单:

DateTime dateTime1 = new DateTime(date1);
DateTime dateTime2 = new DateTime(date2);

int weeks = Weeks.weeksBetween(dateTime1, dateTime2).getWeeks();
Run Code Online (Sandbox Code Playgroud)

  • 正确答案,但过时了。[Joda-Time](http://www.joda.org/joda-time/)的创建者表示,我们应该迁移到[java.time](http://docs.oracle.com/javase/8 /docs/api/java/time/package-summary.html)框架。 (2认同)

Tec*_*rip 27

更新Java 8帐户的答案

// TechTrip - ASSUMPTION d1 is earlier than d2
// leave that for exercise
public static long getFullWeeks(Calendar d1, Calendar d2){

    Instant d1i = Instant.ofEpochMilli(d1.getTimeInMillis());
    Instant d2i = Instant.ofEpochMilli(d2.getTimeInMillis());

    LocalDateTime startDate = LocalDateTime.ofInstant(d1i, ZoneId.systemDefault());
    LocalDateTime endDate = LocalDateTime.ofInstant(d2i, ZoneId.systemDefault());

    return ChronoUnit.WEEKS.between(startDate, endDate);
}
Run Code Online (Sandbox Code Playgroud)

  • 在这里,如果我给出2018年2月28日和2019年3月2日,它计算的是1周,它应该计算2周。你帮我算一下吗? (2认同)

Bas*_*que 12

tl;博士

ChronoUnit
.WEEKS
.between(
    myJavaUtilDate_Start.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) ) , 
    myJavaUtilDate_Stop.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) ) 
)
Run Code Online (Sandbox Code Playgroud)

7

时间

java.time框架是建立在Java 8和更高版本。这些新类取代了与最早版本的 Java 捆绑在一起的旧日期时间类。

java.time类也取代了非常成功的乔达时间框架。无论java.time乔达时间由领导斯蒂芬Colbourne

Java 中的日期时间类型表,现代和传统

Instant 替换 java.util.Date

现代类Instant取代了遗留类java.util.Date。两者都代表 UTC 中的一个时刻,即时间线上的一个特定点。自 UTC 中 1970 年第一时刻的同一纪元参考 1970-01-01T00:00Z 起,两者在内部都使用计数。旧类使用毫秒计数,而Instant使用更精细的纳秒计数。

要进行转换,请调用添加到旧类中的新方法。

Instant start = myJavaUtilDateStart.toInstant() ;
Instant stop = myJavaUtilDateStop.toInstant() ;
Run Code Online (Sandbox Code Playgroud)

让我们用一些示例值来具体说明。

Instant start = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).toInstant();
Instant stop = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).plusWeeks(7 ).toInstant();
Run Code Online (Sandbox Code Playgroud)

时刻与日期

我们的两个Instant对象都代表一个时刻。目标是计算周数。Weeks 表示天,days 表示日历上的某些日期。

所以我们有点不匹配。对于任何给定时刻,日期在全球各地因时区而异。法国巴黎午夜过后的几分钟是一个新的约会。与此同时,在魁北克省蒙特利尔,落后几个小时,同一时刻仍然是“昨天”,也就是日历上的前一天。所以我们不能直接从一对矩计算周数。

您必须首先确定您希望为那些时刻感知日历的时区。

以、、 或等格式指定正确的时区名称。永远不要使用 2-4 个字母的缩写,例如或因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。Continent/RegionAmerica/MontrealAfrica/CasablancaPacific/AucklandESTIST

ZoneId z = ZoneId.of( "America/Montreal" ) ; 
Run Code Online (Sandbox Code Playgroud)

ZonedDateTime

将此ZoneId应用于我们的Instant对象以调整到时区,产生一对ZonedDateTime对象。

ZonedDateTime startZdt = start.atZone( z ) ;
ZonedDateTime stopZdt = stop.atZone( z ) ;
Run Code Online (Sandbox Code Playgroud)

ChronoUnit.WEEKS

现在我们可以使用ChronoUnit枚举来计算经过的周数。

长周 = ChronoUnit.WEEKS.between( startZdt , stopZdt );

转储到控制台。

System.out.println( "start.toString() = " + start );
System.out.println( "stop.toString() = " + stop );
System.out.println( "startZdt.toString() = " + startZdt );
System.out.println( "stopZdt.toString() = " + stopZdt );
System.out.println( "weeksCount: " + weeksCount );
Run Code Online (Sandbox Code Playgroud)

查看此代码在 IdeOne.com 上实时运行

start.toString() = 2020-01-23T15:30:00Z

stop.toString() = 2020-03-12T15:30:00Z

startZdt.toString() = 2020-01-23T10:30-05:00[美国/蒙特利尔]

stopZdt.toString() = 2020-03-12T11:30-04:00[美国/蒙特利尔]

周数:7

三十额外

ThreeTen-EXTRA项目将功能添加到java.time内置到Java 8和更高版本的框架。

Weeks 班级

该项目包括一个Weeks表示周数的类。它不仅可以计算,还可以在您的代码中用作类型安全对象。这种使用还有助于使您的代码自记录。

您可以通过为该Weeks.between方法提供一对时间点来实例化。这些时间点可以是任何实现java.time.temporal.Temporal 的东西,包括Instant, LocalDate, OffsetDateTime, ZonedDateTime, Year, YearMonth, 等等。

您的java.util.Date对象可以轻松转换为Instant对象,UTC 时间轴上的时刻,分辨率为纳秒。查看添加到旧日期时间类的新方法。要从 Date 转到 Instant,请调用java.util.Date::toInstant.

Weeks weeks = Weeks.between( startZdt , stopZdt );
Run Code Online (Sandbox Code Playgroud)

您可以询问周数。

int weeksNumber = weeks.getAmount(); // The number of weeks in this Weeks object.
Run Code Online (Sandbox Code Playgroud)

您还可以做更多的事情。

生成标准ISO 8601格式的字符串。该P标志的开始。该W指示数周。

PW7


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat

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

现在处于维护模式Joda-Time项目建议迁移到java.time类。

您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

从哪里获得 java.time 类?

哪个 java.time 库与哪个版本的 Java 或 Android 一起使用的表

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


Pet*_*ser 8

使用日期算术java.util.Calendar:

public static int getWeeksBetween (Date a, Date b) {

    if (b.before(a)) {
        return -getWeeksBetween(b, a);
    }
    a = resetTime(a);
    b = resetTime(b);

    Calendar cal = new GregorianCalendar();
    cal.setTime(a);
    int weeks = 0;
    while (cal.getTime().before(b)) {
        // add another week
        cal.add(Calendar.WEEK_OF_YEAR, 1);
        weeks++;
    }
    return weeks;
}

public static Date resetTime (Date d) {
    Calendar cal = new GregorianCalendar();
    cal.setTime(d);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    return cal.getTime();
}
Run Code Online (Sandbox Code Playgroud)


SHI*_*IVA 8

如果您的要求是开始日期是 2020 年 4 月 3 日,结束日期是 2020 年 4 月 7 日。两个日期相差 4 天。现在,两个日期之间的周数为 1,您可以使用下面的代码片段。

ChronoUnit.WEEKS.between(LocalDate startDate, LocalDate endDate);
Run Code Online (Sandbox Code Playgroud)

但是,如果您的要求是 2020 年 4 月 3 日在一周内,2020 年 4 月 7 日在另一周内,因此您希望两个日期之间的周数为 2,则可以使用以下代码片段。

LocalDate actualStartDate=...
LocalDate actualEndDate=...

LocalDate startDate = actualStartDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SUNDAY)) 

LocalDate endDate = actualEndDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.SATURDAY)) 

long daysBetweenTwoDates = ChronoUnit.DAYS.between(startDate, endDate);
int numberOfWeeks =  (int)Math.ceil(daysBetweenTwoDates/7.0);
Run Code Online (Sandbox Code Playgroud)

在java 1.8中测试