gnuplot:如何获得正确的周数?

gnuplot:如何获得正确的周数?,gnuplot,week-number,Gnuplot,Week Number,从这个问题出发,, 研究发现,在某些情况下,gnuplot中使用时间说明符%W和%U的周数是错误的 显然,周数有不同的定义。 此外,一周开始时有不同的定义,例如星期日或星期一。 周数的一个定义是根据ISO 8601,这是常用的(但是,在美国和其他一些国家不使用) 代码:(用于说明错误的周数) gnuplot时间说明符: %a abbreviated name of day of the week %w day of the week, 0–6 (Sunday = 0) %d day of the

从这个问题出发,, 研究发现,在某些情况下,gnuplot中使用时间说明符
%W
%U
的周数是错误的

显然,周数有不同的定义。 此外,一周开始时有不同的定义,例如星期日或星期一。 周数的一个定义是根据ISO 8601,这是常用的(但是,在美国和其他一些国家不使用)

代码:(用于说明错误的周数)

gnuplot时间说明符:

%a abbreviated name of day of the week
%w day of the week, 0–6 (Sunday = 0)
%d day of the month, 01–31
%j day of the year, 1–366 
%W week of the year (week starts on Monday)
%U week of the year (week starts on Sunday)
结果:

      date   %a  %w  %d   %j  %W  %U
====================================
24.12.2020  Thu  04  24  359  52  52
25.12.2020  Fri  05  25  360  52  52
26.12.2020  Sat  06  26  361  52  52
27.12.2020  Sun  00  27  362  52  53
28.12.2020  Mon  01  28  363  53  53
29.12.2020  Tue  02  29  364  53  53
30.12.2020  Wed  03  30  365  53  53
31.12.2020  Thu  04  31  366  53  53
01.01.2021  Fri  05  01  001  01  01   ???
02.01.2021  Sat  06  02  002  01  01   ???
03.01.2021  Sun  00  03  003  00  01   ???
04.01.2021  Mon  01  04  004  01  01
05.01.2021  Tue  02  05  005  01  01
06.01.2021  Wed  03  06  006  01  01
07.01.2021  Thu  04  07  007  01  01
08.01.2021  Fri  05  08  008  01  01
09.01.2021  Sat  06  09  009  01  01
10.01.2021  Sun  00  10  010  01  02
11.01.2021  Mon  01  11  011  02  02
12.01.2021  Tue  02  12  012  02  02
13.01.2021  Wed  03  13  013  02  02
### correct week number according to ISO 8601
reset session

dow(t)      = int(tm_wday(t)) ? tm_wday(t) : 7                               # day of week 1=Mon, ..., 7=Sun
week(t)     = int((11 + tm_yday(t) - dow(t))/7)                              # "raw"week of year
wday(d,m,y) = tm_wday(strptime("%d.%m.%Y",sprintf("%02d.%02d.%04d",d,m,y)))  # week day of certain date
wpy(y)      = wday(1,1,y)==4 || wday(31,12,y)==4 ? 53 : 52                   # weeks per year
woy(t)      = week(t) < 1 ? wpy(tm_year(t)-1) : \
              week(t) > wpy(tm_year(t)) ? 1 : week(t)                        # week of year
yow(t)      = int(week(t) < 1 ? tm_year(t)-1 : week(t) > wpy(tm_year(t)) ? \
              tm_year(t)+1 : tm_year(t))                                     # year of week (could be previous, current or next)

StartDate = "24.12.2020"
myTimeFmt = "%d.%m.%Y"
SecondsPerDay = 3600*24

print "      date   %a DoW  %d   %j   YoW WoY"
print "======================================"
do for [i=0:20] {
    t = strptime(myTimeFmt,StartDate) + i*SecondsPerDay
    myDate = strftime(myTimeFmt."  %a", t)
    myDate2 = strftime("%d  %j", t)
    print sprintf("%s  %02d  %s  %04d-W%02d", myDate, dow(t), myDate2, yow(t), woy(t))
}
### end of code
      date   %a DoW  %d   %j   YoW WoY
======================================
24.12.2020  Thu  04  24  359  2020-W52
25.12.2020  Fri  05  25  360  2020-W52
26.12.2020  Sat  06  26  361  2020-W52
27.12.2020  Sun  07  27  362  2020-W52
28.12.2020  Mon  01  28  363  2020-W53
29.12.2020  Tue  02  29  364  2020-W53
30.12.2020  Wed  03  30  365  2020-W53
31.12.2020  Thu  04  31  366  2020-W53
01.01.2021  Fri  05  01  001  2020-W53
02.01.2021  Sat  06  02  002  2020-W53
03.01.2021  Sun  07  03  003  2020-W53
04.01.2021  Mon  01  04  004  2021-W01
05.01.2021  Tue  02  05  005  2021-W01
06.01.2021  Wed  03  06  006  2021-W01
07.01.2021  Thu  04  07  007  2021-W01
08.01.2021  Fri  05  08  008  2021-W01
09.01.2021  Sat  06  09  009  2021-W01
10.01.2021  Sun  07  10  010  2021-W01
11.01.2021  Mon  01  11  011  2021-W02
12.01.2021  Tue  02  12  012  2021-W02
13.01.2021  Wed  03  13  013  2021-W02

问题:是否有解决方法?

根据此处的描述:, 我想ISO 8601定义的本质是:

  • 一周从星期一开始
  • 第01周是一年中第一个星期四所在的一周
  • 一周是指一年中大部分日子都在一周之内
  • 从星期四开始或结束的年份有53周,其他年份有52周
  • 代码:

          date   %a  %w  %d   %j  %W  %U
    ====================================
    24.12.2020  Thu  04  24  359  52  52
    25.12.2020  Fri  05  25  360  52  52
    26.12.2020  Sat  06  26  361  52  52
    27.12.2020  Sun  00  27  362  52  53
    28.12.2020  Mon  01  28  363  53  53
    29.12.2020  Tue  02  29  364  53  53
    30.12.2020  Wed  03  30  365  53  53
    31.12.2020  Thu  04  31  366  53  53
    01.01.2021  Fri  05  01  001  01  01   ???
    02.01.2021  Sat  06  02  002  01  01   ???
    03.01.2021  Sun  00  03  003  00  01   ???
    04.01.2021  Mon  01  04  004  01  01
    05.01.2021  Tue  02  05  005  01  01
    06.01.2021  Wed  03  06  006  01  01
    07.01.2021  Thu  04  07  007  01  01
    08.01.2021  Fri  05  08  008  01  01
    09.01.2021  Sat  06  09  009  01  01
    10.01.2021  Sun  00  10  010  01  02
    11.01.2021  Mon  01  11  011  02  02
    12.01.2021  Tue  02  12  012  02  02
    13.01.2021  Wed  03  13  013  02  02
    
    ### correct week number according to ISO 8601
    reset session
    
    dow(t)      = int(tm_wday(t)) ? tm_wday(t) : 7                               # day of week 1=Mon, ..., 7=Sun
    week(t)     = int((11 + tm_yday(t) - dow(t))/7)                              # "raw"week of year
    wday(d,m,y) = tm_wday(strptime("%d.%m.%Y",sprintf("%02d.%02d.%04d",d,m,y)))  # week day of certain date
    wpy(y)      = wday(1,1,y)==4 || wday(31,12,y)==4 ? 53 : 52                   # weeks per year
    woy(t)      = week(t) < 1 ? wpy(tm_year(t)-1) : \
                  week(t) > wpy(tm_year(t)) ? 1 : week(t)                        # week of year
    yow(t)      = int(week(t) < 1 ? tm_year(t)-1 : week(t) > wpy(tm_year(t)) ? \
                  tm_year(t)+1 : tm_year(t))                                     # year of week (could be previous, current or next)
    
    StartDate = "24.12.2020"
    myTimeFmt = "%d.%m.%Y"
    SecondsPerDay = 3600*24
    
    print "      date   %a DoW  %d   %j   YoW WoY"
    print "======================================"
    do for [i=0:20] {
        t = strptime(myTimeFmt,StartDate) + i*SecondsPerDay
        myDate = strftime(myTimeFmt."  %a", t)
        myDate2 = strftime("%d  %j", t)
        print sprintf("%s  %02d  %s  %04d-W%02d", myDate, dow(t), myDate2, yow(t), woy(t))
    }
    ### end of code
    
          date   %a DoW  %d   %j   YoW WoY
    ======================================
    24.12.2020  Thu  04  24  359  2020-W52
    25.12.2020  Fri  05  25  360  2020-W52
    26.12.2020  Sat  06  26  361  2020-W52
    27.12.2020  Sun  07  27  362  2020-W52
    28.12.2020  Mon  01  28  363  2020-W53
    29.12.2020  Tue  02  29  364  2020-W53
    30.12.2020  Wed  03  30  365  2020-W53
    31.12.2020  Thu  04  31  366  2020-W53
    01.01.2021  Fri  05  01  001  2020-W53
    02.01.2021  Sat  06  02  002  2020-W53
    03.01.2021  Sun  07  03  003  2020-W53
    04.01.2021  Mon  01  04  004  2021-W01
    05.01.2021  Tue  02  05  005  2021-W01
    06.01.2021  Wed  03  06  006  2021-W01
    07.01.2021  Thu  04  07  007  2021-W01
    08.01.2021  Fri  05  08  008  2021-W01
    09.01.2021  Sat  06  09  009  2021-W01
    10.01.2021  Sun  07  10  010  2021-W01
    11.01.2021  Mon  01  11  011  2021-W02
    12.01.2021  Tue  02  12  012  2021-W02
    13.01.2021  Wed  03  13  013  2021-W02
    
    为了使用周数,例如作为时间轴标签,最好在
    %W
    中实现这一点。意外的是,最近在SourceForge上发生了一个事件。
    因此,我认为它将很快在下一个版本中得到修复。

    鉴于目前的大流行以及由此产生的对绘制来自所有来源的流行病学数据的兴趣,清理并扩展gnuplot对周日期格式的支持似乎是权宜之计。gnuplot文档的“新特性”部分现在列出:

    • Time specifier format %W has been brought into accord with the ISO 8601 week date standard. 
    • Time specifier format %U has been brought into accord with the CDC/MMWR week date standard. 
    • New function tm week(time, std) returns ISO or CDC standard week of year. 
    • New function weekdate iso(year, week, day) converts ISO standard week date to calendar time. 
    • New function weekdate cdc(year, week, day) converts CDC standard week date to calendar time.
    
    下面是一个将ISO 8601 week date格式中给出的数据转换为标准日历日期以沿gnuplot时间轴绘制的示例(从)

    #                   Epidemiological data
    #
    # Plot from data file that encodes date as an ISO 8601 "week date".
    # Example:  week date 2004-W01-1 is calendar date 29 December 2003
    # The data is from the European Centre for Disease Prevention and Control
    # https://www.ecdc.europa.eu/
    
    # The ECDC data file uses fields containing week date as "YYYY-WW".
    # First we define a function that extracts the integer year and week
    # from this string and converts it to standard time representation.
    
    calendar(date) = weekdate_iso( int(date[1:4]), int(date[6:7]) )
    
    set datafile separator comma
    set style data lines
    set key Left left reverse box samplen 2 width 2
    set grid x lt 1 lw .75 lc "gray"
    set tics nomirror
    set border 3
    set xtics time format "%b\n%Y"
    set ytics format " %4.0f"
    
    data1 = '< grep "Denmark.*cases" ECDC-weekly-national-COVID.csv'
    data2 = '< grep "Sweden.*cases" ECDC-weekly-national-COVID.csv'
    data3 = '< grep "Norway.*cases" ECDC-weekly-national-COVID.csv'
    data4 = '< grep "Finland.*cases" ECDC-weekly-national-COVID.csv'
    data5 = '< grep "Iceland.*cases" ECDC-weekly-national-COVID.csv'
    
    set title "weekly COVID-19 cases per 100,000 people" font "/Bold,15"
    
    plot data1 using (calendar(strcol(7))) : (1.e5*$6/$4) lw 2 title "Denmark", \
         data2 using (calendar(strcol(7))) : (1.e5*$6/$4) lw 2 title "Sweden", \
         data3 using (calendar(strcol(7))) : (1.e5*$6/$4) lw 2 title "Norway", \
         data4 using (calendar(strcol(7))) : (1.e5*$6/$4) lw 2 title "Finland", \
         data5 using (calendar(strcol(7))) : (1.e5*$6/$4) lw 2 lt 6 title "Iceland"
    
    流行病学数据 # #从将日期编码为ISO 8601“周日期”的数据文件打印。 #示例:周日期2004-W01-1是日历日期2003年12月29日 #数据来自欧洲疾病预防和控制中心 # https://www.ecdc.europa.eu/ #ECDC数据文件使用包含周日期为“YYYY-WW”的字段。 #首先,我们定义一个函数来提取整数年和周 #并将其转换为标准时间表示形式。 日历(日期)=工作日(国际标准化组织(日期[1:4]),国际标准化组织(日期[6:7])) 设置数据文件分隔符逗号 设置样式数据行 设置钥匙左反转盒samplen 2宽度2 设置网格x lt 1 lw.75 lc“灰色” 设置错误 设置边框3 设置xtics时间格式“%b\n%Y” 设置ytics格式“%4.0f” 数据1=“

    是的,现在在gnuplot git存储库中有一个%W格式的修复程序。就我所了解的ISO 8601“周日期”标准而言,您列出的四个属性都是基本定义“一年的第一周从最接近当年1月1日的星期一开始”的必然结果。