Создание случайной даты между двумя другими датами



Как бы я создать произвольную дату, которая должна быть между двумя заданными датами?
Сигнатура функции должна быть примерно такой -



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

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


и вернуть дату, например-
"2/4/2008 7: 20 PM"

682   22  

22 ответов:

преобразуйте обе строки в метки времени (в выбранном вами разрешении, например, миллисекунды, секунды, часы, дни, что угодно), вычитайте более раннее из более позднего, умножьте свое случайное число (предполагая, что оно распределено в диапазоне [0, 1]) с этой разницей и снова добавьте к более раннему. Преобразуйте метку времени обратно в строку даты, и у вас есть случайное время в этом диапазоне.

пример Python (вывод почти в указанном вами формате, кроме 0 padding-виноват Американский формат времени конвенций):

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())
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

крошечная версия.

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())),
    )

обратите внимание, что оба start и end аргументы должны быть datetime объекты. Если у вас есть строки вместо этого, это довольно легко конвертировать. Другие ответы указывают к некоторым способам сделать это.

обновил ответ

это еще более просто с помощью 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)

ответ

это очень просто с помощью радара

установка

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()

это другой подход - такого рода работ..

from random import randint
import datetime

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

WAIITT-ЛУЧШИЙ ПОДХОД

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

Начиная С Python 3 timedelta поддерживает умножение с поплавками, так что теперь вы можете сделать:

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

учитывая, что start и end типа datetime.datetime. Например, чтобы сгенерировать случайную дату и время в течение следующего дня:

import random
from datetime import datetime, timedelta

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

для чипирования решения на основе панд я использую:

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)

самый простой способ сделать это-преобразовать оба числа в метки времени, а затем установить их как минимальную и максимальную границы для генератора случайных чисел.

быстрый пример 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() чтобы сделать допустимую дату из случайной метки времени, которая была сгенерирована.

можно использовать 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))

вот ответ на буквальный смысл названия, а не тело этот вопрос:

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)

этот код основан свободно на принятом ответе.

просто добавить еще один:

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 вы находитесь на защищенном сайте.

  1. преобразование даты ввода чисел (int, float, все, что лучше всего подходит использования)
  2. выбрать число между двумя числами.
  3. преобразовать это число обратно в дату.

многие алгоритмы для преобразования даты и цифры уже доступны во многих операционных системах.

для чего вам нужно случайное число? Обычно (в зависимости от языка) вы можете получить количество секунд/миллисекунд от эпохи от дата. Так что для случайной даты между startDate и endDate вы могли бы сделать:

  1. вычислить время в мс между StartDate и enddate (конец света.томиллисекунды() - дата начала.toMilliseconds ())
  2. сгенерируйте число между 0 и числом, полученным в 1
  3. создать новую дату со смещением = дата начала.toMilliseconds () + число, полученное в 2

вот решение, модифицированное из подхода эмиллера, который возвращает массив случайных дат при любом разрешении

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 действительно хорош в приведении вещей к датам, поэтому вы можете указать даты начала/окончания в виде строк, дат, временных меток панд... почти все будет работать.

#!/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()

концептуально это довольно просто. В зависимости от того, какой язык вы используете, вы сможете конвертировать эти даты в некоторое эталонное 32 или 64-разрядное целое число, обычно представляющее секунды с эпохи (1 января 1970 года), иначе известной как "время Unix" или миллисекунды с некоторой другой произвольной даты. Просто генерировать случайный 32-или 64-разрядное целое число между этими двумя значениями. Это должен быть один лайнер на любом языке.

на некоторых платформах вы можете создать время как двойной (дата-это целая часть, время-дробная часть-это одна реализация). Тот же принцип применяется, за исключением того, что вы имеете дело с числами с плавающей запятой одиночной или двойной точности ("плавает" или "удваивается" на C, Java и других языках). Вычтите разницу, умножьте на случайное число (0

используйте ApacheCommonUtils для генерации случайной длины в заданном диапазоне, а затем создать дату из этого длинного.

пример:

импорт орг.апаш.палата общин.математика.случайность.RandomData;

импорт орг.апаш.палата общин.математика.случайность.RandomDataImpl;

публичная дата nextDate (дата min, дата max) {

RandomData randomData = new RandomDataImpl();

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

}

Я сделал это для другого проекта, используя случайные и времени. Я использовал обычный формат времени вы можете просмотреть документацию здесь для первого аргумента в функцию strftime(). Вторая часть-случайная.функция randrange. Он возвращает целое число между аргументами. Измените его на диапазоны, соответствующие строкам, которые вы хотите. У вас должны быть хорошие аргументы в кортеже второго arugment.

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))

панды + numpy решение

import pandas as pd
import numpy as np

def RandomTimestamp(start, end):
    dts = (end - start).total_seconds()
    return start + pd.Timedelta(np.random.uniform(0, dts), 's')

dts-это разница между метками времени в секундах (float). Затем он используется для создания панды timedelta между 0 и dts, который добавляется в метку времени начала.

основываясь на ответе mouviciel, вот векторизованное решение с использованием numpy. Преобразуйте даты начала и окончания в ints, сгенерируйте массив случайных чисел между ними и преобразуйте весь массив обратно в даты.

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

это модифицированный метод @(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

в 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)

Comments

    Ничего не найдено.