什么是计算ISO 8601周数的简单好方法?

时间:2020-03-06 14:51:25  来源:igfitidea点击:

假设我有一个日期,即年,月和日,为整数。什么是计算给定日期所属的星期的ISO 8601周数的一种好(正确),简洁且可读性强的算法?我遇到了一些真正可怕的代码,这些代码使我认为肯定有更好的方法。

我正在寻找使用Java进行此操作的方法,但是对于任何一种面向对象的语言,psuedocode都可以。

解决方案

我相信我们可以使用Calendar对象(只需将FirstDayOfWeek设置为Monday,将MinimalDaysInFirstWeek设置为4,使其符合ISO 8601),然后调用get(Calendar.WEEK_OF_YEAR)。

joda-time库具有ISO8601日历,并提供以下功能:

http://joda-time.sourceforge.net/cal_iso.html

yyyy-Www-dTHH:MM:SS.SSS This format of
  ISO8601 has the following fields:

* four digit weekyear, see rules below
* two digit week of year, from 01 to 53
* one digit day of week, from 1 to 7 where 1 is Monday and 7 is Sunday
* two digit hour, from 00 to 23
* two digit minute, from 00 to 59
* two digit second, from 00 to 59
* three decimal places for milliseconds if required

  
  Weeks are always complete, and the
  first week of a year is the one that
  includes the first Thursday of the
  year. This definition can mean that
  the first week of a year starts in the
  previous year, and the last week
  finishes in the next year. The
  weekyear field is defined to refer to
  the year that owns the week, which may
  differ from the actual year.

这就是创建一个DateTime对象,并调用相当混乱(但在逻辑上)的getWeekOfWeekyear()的结果,其中weekyear是ISO8601使用的基于周的特定定义。

通常,joda-time是一个非常有用的API,除了需要与使用它们的API接口时,我已经完全停止使用java.util.Calendar和java.util.Date。

如果我们想处于最前沿,可以使用由Joda Fame的Stephen Colebourne领导的最新版本的JSR-310代码库(日期时间API)。它的界面流畅,实际上是对Joda的自下而上的重新设计。

这是相反的:给我们星期几(在perl中)

use POSIX qw(mktime);
use Time::localtime;

sub monday_of_week {
    my $year=shift;
    my $week=shift;
    my $p_date=shift;

    my $seconds_1_jan=mktime(0,0,0,1,0,$year-1900,0,0,0);
    my $t1=localtime($seconds_1_jan);
    my $seconds_for_week;
    if (@$t1[6] < 5) {
#first of january is a thursday (or below)
        $seconds_for_week=$seconds_1_jan+3600*24*(7*($week-1)-@$t1[6]+1);
    } else {
        $seconds_for_week=$seconds_1_jan+3600*24*(7*($week-1)-@$t1[6]+8);
    }
    my $wt=localtime($seconds_for_week);
    $$p_date=sprintf("%02d/%02d/%04d",@$wt[3],@$wt[4]+1,@$wt[5]+1900);
}