在给定年份间隔的情况下,如何生成随机日期序列?

在给定年份间隔的情况下,如何生成随机日期序列?

这里需要一个命令,在给定年份范围(1987 到 2017)的情况下生成六个日期。例如:

12/10/1987
30/04/1998
22/02/2014
17/08/2017
19/07/2011
14/05/2004

sed如何用、等来完成gawk

答案1

date,shufxargs:

将开始和结束日期转换为“自 1970-01-01 00:00:00 UTC 以来的秒数”,并用于shuf打印此范围内的六个随机值。将此结果通过管道传输xargs并将值转换为所需的日期格式。

编辑:如果您希望输出中包含 2017 年的日期,则需要2017-12-31 23:59:59在结束日期中添加一年 -1s ( )。shuf -i生成随机数,包括开始和结束。

shuf -n6 -i$(date -d '1987-01-01' '+%s')-$(date -d '2017-01-01' '+%s')\
 | xargs -I{} date -d '@{}' '+%d/%m/%Y'

输出示例:

07/12/1988
22/04/2012
24/09/2012
27/08/2000
19/01/2008
21/10/1994

答案2

您可以将问题转化为在表示第一个可能日期的数字和表示最后一个可能日期(实际上是最后一个可能日期之后的日期)的数字之间生成一个随机数,采用 Unix 纪元格式。其他一切都由标准日期转换处理。gawk具有比(浮点与 15 位整数)更好的随机数分辨率bash,因此我将使用gawk.请注意,rand()结果 N 是浮点数,使得 0 <= N < 1,这就是为什么上限会增加到下面,这是一个无法滚动的限制。有一个可选的第三个参数用于表示结果数。

#!/usr/bin/gawk -f
BEGIN {
    first=mktime(ARGV[1] " 01 01 00 00 00")
    last=mktime(ARGV[2]+1 " 01 01 00 00 00")
    if (ARGC == 4) { num=ARGV[3] } else { num=1 }
    ARGC=1
    range=last-first
    srand(sprintf("%d%06d", systime(), PROCINFO["pid"]))
    for (i=1; i <= num; i++) {
        print strftime("%d/%m/%Y", range*rand()+first)
    }
}   

例如:

./randomdate.gawk 1987 2017 6
26/04/1992
28/04/2010
21/04/2005
17/02/2010
06/10/2016
04/04/1998

答案3

珀尔:

perl -MTime::Piece -sE '
    my $t1 = Time::Piece->strptime("$y1-01-01 00:00:00", "%Y-%m-%d %H:%M:%S");
    my $t2 = Time::Piece->strptime("$y2-12-31 23:59:59", "%Y-%m-%d %H:%M:%S");
    do {
        my $time = $t1 + int(rand() * ($t2 - $t1));
        say $time->dmy;
    } for 1..6;
' -- -y1=1987 -y2=2017

示例输出:

10-01-1989
30-04-1995
10-12-1998
02-01-2016
04-06-2006
11-04-1987

答案4

如果年数差异小于大约 90,您可以使用$RANDOMbash 中的变量来提供天数偏移量,并使用date命令的有限能力进行计算。

#!/bin/bash
s=$(date +%s -d "1/1/$1")          # start in seconds since 1 Jan 1970
e=$(date +%s -d "1/1/$(($2+1))")   # start of end year +1 in seconds
days=$(((e-s)/(24*3600)))          # number of days from start to end
factor=$((32767/$days))            # RANDOM is 0 to 32767. See how many
toobig=$(($factor*$days))          # exact multiples of days.
                                   # if RANDOM is too large, draw again
for((i=0;i<${3:-1};i++))           # produce $3 random dates
do
    r=$RANDOM                      # find a random number < toobig
    while (( r >= toobig ))        # if toobig, then loop.
    do r=$RANDOM
    done
    offset=$(($r/$factor))         # get (0,days) from (0,factor*days)
    # output horrible day/month/year for N days past start date
    date -d "$offset days 1/1/$1" +%d/%m/%Y
done

选择随机数的内部循环尝试纠正偏差。如果随机数源可以均匀地为您提供 0、1、2、3、4、5、6、7、8 或 9,并且您想要一个介于 0 和 3(含)之间的随机数,那么如果您从源中获得 0 或 1你报告0,如果你得到2或3,那么你报告1,如果你得到4或5,你报告2,如果你得到6或7,你报告3,如果你得到8或9,你忽略源中的这个数字。

相关内容