在两个其他日期之间生成随机日期

时间:2009-02-16 13:30:04

标签: python datetime random

我如何生成一个必须在两个其他给定日期之间的随机日期?

函数的签名应该是这样的:

randomDate("1/1/2008 1:30 PM", "1/1/2009 4:50 AM", 0.34)
                  ^                       ^          ^

           date generated has   date generated has a random number
           to be after this     to be before this

并返回日期,例如:2/4/2008 7:20 PM

29 个答案:

答案 0 :(得分:114)

将两个字符串转换为时间戳(以您选择的分辨率,例如毫秒,秒,小时,天等),从较晚的时间减去前一个,乘以您的随机数(假设它分布在range [0, 1])有这种差异,并再次添加到前一个。将时间戳转换回日期字符串,您在该范围内有一个随机时间。

Python示例(输出几乎采用您指定的格式,而不是0填充 - 归咎于美国时间格式约定):

import random
import time

def strTimeProp(start, end, format, prop):
    """Get a time at a proportion of a range of two formatted times.

    start and end should be strings specifying times formated in the
    given format (strftime-style), giving an interval [start, end].
    prop specifies how a proportion of the interval to be taken after
    start.  The returned time will be in the specified format.
    """

    stime = time.mktime(time.strptime(start, format))
    etime = time.mktime(time.strptime(end, format))

    ptime = stime + prop * (etime - stime)

    return time.strftime(format, time.localtime(ptime))


def randomDate(start, end, prop):
    return strTimeProp(start, end, '%m/%d/%Y %I:%M %p', prop)

print randomDate("1/1/2008 1:30 PM", "1/1/2009 4:50 AM", random.random())

答案 1 :(得分:90)

from random import randrange
from datetime import timedelta

def random_date(start, end):
    """
    This function will return a random datetime between two datetime 
    objects.
    """
    delta = end - start
    int_delta = (delta.days * 24 * 60 * 60) + delta.seconds
    random_second = randrange(int_delta)
    return start + timedelta(seconds=random_second)

精度是秒。如果需要,您可以将精度提高到微秒,或者减少到半小时。为此,只需更改最后一行计算。

示例运行:

d1 = datetime.strptime('1/1/2008 1:30 PM', '%m/%d/%Y %I:%M %p')
d2 = datetime.strptime('1/1/2009 4:50 AM', '%m/%d/%Y %I:%M %p')

print random_date(d1, d2)

输出:

2008-12-04 01:50:17

答案 2 :(得分:74)

一个小版本。

import datetime
import random


def random_date(start, end):
    """Generate a random datetime between `start` and `end`"""
    return start + datetime.timedelta(
        # Get a random amount of seconds between `start` and `end`
        seconds=random.randint(0, int((end - start).total_seconds())),
    )

请注意,startend参数都应为datetime个对象。如果 你有字符串,它很容易转换。其他答案指出 在某些方面这样做。

答案 3 :(得分:38)

更新回答

使用Faker更简单。

安装

pip install faker

用法:

from faker import Faker
fake = Faker()

fake.date_between(start_date='today', end_date='+30y')
# datetime.date(2025, 3, 12)

fake.date_time_between(start_date='-30y', end_date='now')
# datetime.datetime(2007, 2, 28, 11, 28, 16)

# Or if you need a more specific date boundaries, provide the start 
# and end dates explicitly.
import datetime
start_date = datetime.date(year=2015, month=1, day=1)
fake.date_between(start_date=start_date, end_date='+30y')

旧答案

使用雷达非常简单

安装

pip install radar

用法

import datetime

import radar 

# Generate random datetime (parsing dates from str values)
radar.random_datetime(start='2000-05-24', stop='2013-05-24T23:59:59')

# Generate random datetime from datetime.datetime values
radar.random_datetime(
    start = datetime.datetime(year=2000, month=5, day=24),
    stop = datetime.datetime(year=2013, month=5, day=24)
)

# Just render some random datetime. If no range is given, start defaults to 
# 1970-01-01 and stop defaults to datetime.datetime.now()
radar.random_datetime()

答案 4 :(得分:16)

这是一种不同的方法 - 这种方式......

from random import randint
import datetime

date=datetime.date(randint(2005,2025), randint(1,12),randint(1,28))

更好的方法

startdate=datetime.date(YYYY,MM,DD)
date=startdate+datetime.timedelta(randint(1,365))

答案 5 :(得分:11)

由于Python 3 timedelta支持乘法浮点数,所以现在你可以这样做:

import random
random_date = start + (end - start) * random.random()

鉴于startend属于datetime.datetime类型。例如,要在第二天生成随机日期时间:

import random
from datetime import datetime, timedelta

start = datetime.now()
end = start + timedelta(days=1)
random_date = start + (end - start) * random.random()

答案 6 :(得分:6)

为了插入基于熊猫的解决方案,我使用:

import pandas as pd
import numpy as np

def random_date(start, end, position=None):
    start, end = pd.Timestamp(start), pd.Timestamp(end)
    delta = (end - start).total_seconds()
    if position is None:
        offset = np.random.uniform(0., delta)
    else:
        offset = position * delta
    offset = pd.offsets.Second(offset)
    t = start + offset
    return t

我喜欢它,因为有很好的pd.Timestamp功能,可以让我在它上面添加不同的东西和格式。考虑以下几个例子......

你的签名。

>>> random_date(start="1/1/2008 1:30 PM", end="1/1/2009 4:50 AM", position=0.34)
Timestamp('2008-05-04 21:06:48', tz=None)

随机位置。

>>> random_date(start="1/1/2008 1:30 PM", end="1/1/2009 4:50 AM")
Timestamp('2008-10-21 05:30:10', tz=None)

格式不同。

>>> random_date('2008-01-01 13:30', '2009-01-01 4:50')
Timestamp('2008-11-18 17:20:19', tz=None)

直接传递pandas / datetime对象。

>>> random_date(pd.datetime.now(), pd.datetime.now() + pd.offsets.Hour(3))
Timestamp('2014-03-06 14:51:16.035965', tz=None)

答案 7 :(得分:3)

您可以使用Mixer

pip install mixer

from mixer import generators as gen
print gen.get_datetime(min_datetime=(1900, 1, 1, 0, 0, 0), max_datetime=(2020, 12, 31, 23, 59, 59))

答案 8 :(得分:2)

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Create random datetime object."""

from datetime import datetime
import random


def create_random_datetime(from_date, to_date, rand_type='uniform'):
    """
    Create random date within timeframe.

    Parameters
    ----------
    from_date : datetime object
    to_date : datetime object
    rand_type : {'uniform'}

    Examples
    --------
    >>> random.seed(28041990)
    >>> create_random_datetime(datetime(1990, 4, 28), datetime(2000, 12, 31))
    datetime.datetime(1998, 12, 13, 23, 38, 0, 121628)
    >>> create_random_datetime(datetime(1990, 4, 28), datetime(2000, 12, 31))
    datetime.datetime(2000, 3, 19, 19, 24, 31, 193940)
    """
    delta = to_date - from_date
    if rand_type == 'uniform':
        rand = random.random()
    else:
        raise NotImplementedError('Unknown random mode \'{}\''
                                  .format(rand_type))
    return from_date + rand * delta


if __name__ == '__main__':
    import doctest
    doctest.testmod()

答案 9 :(得分:2)

最简单的方法是将两个数字转换为时间戳,然后将它们设置为随机数生成器的最小和最大边界。

一个简单的PHP例子是:

// Find a randomDate between $start_date and $end_date
function randomDate($start_date, $end_date)
{
    // Convert to timetamps
    $min = strtotime($start_date);
    $max = strtotime($end_date);

    // Generate random number using above bounds
    $val = rand($min, $max);

    // Convert back to desired date format
    return date('Y-m-d H:i:s', $val);
}

此函数使用strtotime()将日期时间描述转换为Unix时间戳,使用date()使有效日期超出已生成的随机时间戳。

答案 10 :(得分:2)

这是对标题的字面含义的回答,而不是这个问题的正文:

import time
import datetime
import random

def date_to_timestamp(d) :
  return int(time.mktime(d.timetuple()))

def randomDate(start, end):
  """Get a random date between two dates"""

  stime = date_to_timestamp(start)
  etime = date_to_timestamp(end)

  ptime = stime + random.random() * (etime - stime)

  return datetime.date.fromtimestamp(ptime)

此代码基于接受的答案。

答案 11 :(得分:2)

只是添加另一个:

datestring = datetime.datetime.strftime(datetime.datetime( \
    random.randint(2000, 2015), \
    random.randint(1, 12), \
    random.randint(1, 28), \
    random.randrange(23), \
    random.randrange(59), \
    random.randrange(59), \
    random.randrange(1000000)), '%Y-%m-%d %H:%M:%S')

日处理需要一些考虑因素。有28位你就在安全的网站上。

答案 12 :(得分:1)

  1. 将输入日期转换为数字 (int,float,无论什么是最好的 你的用法)
  2. 在两个日期编号之间选择一个数字。
  3. 将此号码转换回日期。
  4. 许多操作系统已经提供了许多用于将日期转换为数字的算法。

答案 13 :(得分:1)

将日期转换为时间戳,并使用时间戳调用random.randint,然后将随机生成的时间戳转换回日期:

from datetime import datetime
import random

def random_date(first_date, second_date):
    first_timestamp = int(first_date.timestamp())
    second_timestamp = int(second_date.timestamp())
    random_timestamp = random.randint(first_timestamp, second_timestamp)
    return datetime.fromtimestamp(random_timestamp)

然后您可以像这样使用它

from datetime import datetime

d1 = datetime.strptime("1/1/2018 1:30 PM", "%m/%d/%Y %I:%M %p")
d2 = datetime.strptime("1/1/2019 4:50 AM", "%m/%d/%Y %I:%M %p")

random_date(d1, d2)

random_date(d2, d1)  # ValueError because the first date comes after the second date

如果您关心时区,则应该使用fakerwhere I stole this code from,因为已经给出了另一个答案。

答案 14 :(得分:1)

这是一个从emyller方法修改的解决方案,它以任何分辨率返回随机日期数组

import numpy as np

def random_dates(start, end, size=1, resolution='s'):
    """
    Returns an array of random dates in the interval [start, end]. Valid 
    resolution arguments are numpy date/time units, as documented at: 
        https://docs.scipy.org/doc/numpy-dev/reference/arrays.datetime.html
    """
    start, end = np.datetime64(start), np.datetime64(end)
    delta = (end-start).astype('timedelta64[{}]'.format(resolution))
    delta_mat = np.random.randint(0, delta.astype('int'), size)
    return start + delta_mat.astype('timedelta64[{}]'.format(resolution))

这种方法的优点之一是np.datetime64非常善于将事情强制转换为日期,因此您可以将开始/结束日期指定为字符串,日期时间,熊猫时间戳...漂亮什么都行不通。

答案 15 :(得分:1)

你需要什么随机数?通常(取决于语言)您可以从日期获得Epoch的秒数/毫秒数。因此,对于startDate和endDate之间的随机日期,您可以执行以下操作:

  1. 计算之间的毫秒数 startDate和endDate (endDate.toMilliseconds() - startDate.toMilliseconds())
  2. 生成0到您在1
  3. 中获得的数字之间的数字
  4. 生成一个新的日期,时间偏移= startDate.toMilliseconds()+数字获得2

答案 16 :(得分:0)

我使用随机和时间为另一个项目做了这个。我使用了一般格式,你可以在strftime()中查看文档here的第一个参数。第二部分是random.randrange函数。它返回参数之间的整数。将其更改为与您希望的字符串匹配的范围。你必须在第二个句子的元组中有很好的论据。

import time
import random


def get_random_date():
    return strftime("%Y-%m-%d %H:%M:%S",(random.randrange(2000,2016),random.randrange(1,12),
    random.randrange(1,28),random.randrange(1,24),random.randrange(1,60),random.randrange(1,60),random.randrange(1,7),random.randrange(0,366),1))

答案 17 :(得分:0)

使用ApacheCommonUtils在给定范围内生成随机长度, 然后创建那个漫长的日期。

示例:

import org.apache.commons.math.random.RandomData;

import org.apache.commons.math.random.RandomDataImpl;

public Date nextDate(Date min,Date max){

RandomData randomData = new RandomDataImpl();

return new Date(randomData.nextLong(min.getTime(), max.getTime()));

}

答案 18 :(得分:0)

Pandas + numpy solution

var root = JsonConvert.DeserializeObject<Root>(json, new CustomClassConverter());

dts是以秒为单位的时间戳(浮点数)之间的差异。然后用它来创建一个介于0和dts之间的pandas timedelta,它被添加到开始时间戳中。

答案 19 :(得分:0)

根据mouviciel的回答,这是一个使用numpy的矢量化解决方案。将开始日期和结束日期转换为整数,在它们之间生成一个随机数组,并将整个数组转换回日期。

import time
import datetime
import numpy as np

n_rows = 10

start_time = "01/12/2011"
end_time = "05/08/2017"

date2int = lambda s: time.mktime(datetime.datetime.strptime(s,"%d/%m/%Y").timetuple())
int2date = lambda s: datetime.datetime.fromtimestamp(s).strftime('%Y-%m-%d %H:%M:%S')

start_time = date2int(start_time)
end_time = date2int(end_time)

random_ints = np.random.randint(low=start_time, high=end_time, size=(n_rows,1))
random_dates = np.apply_along_axis(int2date, 1, random_ints).reshape(n_rows,1)

print random_dates

答案 20 :(得分:0)

这是@(Tom Alsberg)的修改方法。我将其修改为以毫秒为单位获取日期。

import random
import time
import datetime

def random_date(start_time_string, end_time_string, format_string, random_number):
    """
    Get a time at a proportion of a range of two formatted times.
    start and end should be strings specifying times formated in the
    given format (strftime-style), giving an interval [start, end].
    prop specifies how a proportion of the interval to be taken after
    start.  The returned time will be in the specified format.
    """
    dt_start = datetime.datetime.strptime(start_time_string, format_string)
    dt_end = datetime.datetime.strptime(end_time_string, format_string)

    start_time = time.mktime(dt_start.timetuple()) + dt_start.microsecond / 1000000.0
    end_time = time.mktime(dt_end.timetuple()) + dt_end.microsecond / 1000000.0

    random_time = start_time + random_number * (end_time - start_time)

    return datetime.datetime.fromtimestamp(random_time).strftime(format_string)

示例:

print TestData.TestData.random_date("2000/01/01 00:00:00.000000", "2049/12/31 23:59:59.999999", '%Y/%m/%d %H:%M:%S.%f', random.random())

输出:2028/07/08 12:34:49.977963

答案 21 :(得分:0)

在python中:

>>> from dateutil.rrule import rrule, DAILY
>>> import datetime, random
>>> random.choice(
                 list(
                     rrule(DAILY, 
                           dtstart=datetime.date(2009,8,21), 
                           until=datetime.date(2010,10,12))
                     )
                 )
datetime.datetime(2010, 2, 1, 0, 0)

(需要python dateutil库 - pip install python-dateutil

答案 22 :(得分:0)

从概念上讲,这很简单。根据您使用的语言,您可以将这些日期转换为某个参考32或64位整数,通常表示自纪元(1970年1月1日)以来的秒数(也称为“Unix时间”)或自其他任意日期以来的毫秒数。只需在这两个值之间生成一个随机的32或64位整数。这应该是任何语言的单行。

在某些平台上,您可以生成一个双倍的时间(日期是整数部分,时间是小数部分是一个实现)。除了处理单精度或双精度浮点数(C,Java和其他语言中的“浮点数”或“双精度数”)之外,同样的原则适用。减去差值,乘以随机数(0 <= r <= 1),加上开始时间并完成。

答案 23 :(得分:0)

start_timestamp = time.mktime(time.strptime('Jun 1 2010  01:33:00', '%b %d %Y %I:%M:%S'))
end_timestamp = time.mktime(time.strptime('Jun 1 2017  12:33:00', '%b %d %Y %I:%M:%S'))
time.strftime('%b %d %Y %I:%M:%S',time.localtime(randrange(start_timestamp,end_timestamp)))

refer

答案 24 :(得分:0)

    # needed to create data for 1000 fictitious employees for testing code 
    # code relating to randomly assigning forenames, surnames, and genders
    # has been removed as not germaine to the question asked above but FYI
    # genders were randomly assigned, forenames/surnames were web scrapped,
    # there is no accounting for leap years, and the data stored in mySQL

    import random 
    from datetime import datetime
    from datetime import timedelta

    for employee in range(1000):
        # assign a random date of birth (employees are aged between sixteen and sixty five)
        dlt = random.randint(365*16, 365*65)
        dob = datetime.today() - timedelta(days=dlt)
        # assign a random date of hire sometime between sixteenth birthday and yesterday
        doh = datetime.today() - timedelta(days=random.randint(1, dlt-365*16))
        print("born {} hired {}".format(dob.strftime("%d-%m-%y"), doh.strftime("%d-%m-%y")))

答案 25 :(得分:0)

使用<h1 data-editable>First h1</h1> <p data-editable>First Element</p> <p data-editable>Second Element</p> <p>Not editable</p>SELECT DISTINCT test_id, FIRST_VALUE(test_date) OVER (PARTITION BY test_id,MONTH(test_date), YEAR(test_date) ORDER BY test_date desc ) as test_date, FIRST_VALUE(test_date_from) OVER (PARTITION BY test_id,MONTH(test_date), YEAR(test_date) ORDER BY test_date desc ) as test_date_from, FIRST_VALUE(cash_per_step) OVER (PARTITION BY test_id,MONTH(test_date), YEAR(test_date) ORDER BY test_date desc ) as cash_per_step FROM YourTable np.random.randint()pd.Timestamp().value在两个日期之间创建随机日期的替代方法:

pd.to_datetime()

输出

for loop

答案 26 :(得分:0)

在 start_date 和 end_date 之间获取随机日期。 如果其中任何一个为 None,则在两者之间获取随机日期 今天和过去 100 年。

class GetRandomDateMixin:
    def get_random_date(self, start_date=None, end_date=None):
        """
        get random date between start_date and end_date.
        If any of them is None, then get random date between
        today and past 100 years.
        :param start_date: datetime obj.
            eg: datetime.datetime(1940, 1, 1).date()
        :param end_date: datetime obj
        :return: random date
        """
        if start_date is None or end_date is None:

            end_date = datetime.datetime.today().date()
            start_date = end_date - datetime.timedelta(
                days=(100 * 365)
            )

        delta = end_date - start_date
        random_days = random.randint(1, delta.days)
        new_date = start_date + datetime.timedelta(
            days=random_days
        )

        return new_date

答案 27 :(得分:0)

建立在@Pieter Bos 的回答之上:

import random
import datetime

start = datetime.date(1980, 1, 1)
end = datetime.date(2000, 1, 1)

random_date = start + (end - start) * random.random()
random_date = datetime.datetime.combine(random_date, datetime.datetime.min.time())

答案 28 :(得分:0)

怎么样

import datetime
import random


def random_date(begin: datetime.datetime, end: datetime.datetime):
    epoch = datetime.datetime(1970, 1, 1)
    begin_seconds = int((begin - epoch).total_seconds())
    end_seconds = int((end - epoch).total_seconds())
    dt_seconds = random.randint(begin_seconds, end_seconds)

    return datetime.datetime.fromtimestamp(dt_seconds)

还没有尝试过与 1970 年不同的“纪元”年,但它确实有效