Comment pourrais-je générer une date aléatoire qui doit se situer entre deux autres dates données?
La signature de la fonction devrait ressembler à ceci:
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
et retournerait une date telle que: 2/4/2008 7:20 PM
Convertissez les deux chaînes en horodatages (dans la résolution de votre choix, par exemple millisecondes, secondes, heures, jours, etc.), soustrayez le plus tôt possible, multipliez votre nombre aléatoire (en supposant qu'il soit distribué dans le range [0, 1]
) avec cette différence, puis ajoutez à la précédente. Convertissez l'horodatage en chaîne de date et vous avez une heure aléatoire dans cette plage.
Exemple Python (la sortie est presque au format que vous avez spécifié, à l'exception de 0
padding - reprocher aux conventions de format d'heure américaines):
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)
La précision est en secondes. Vous pouvez augmenter la précision jusqu’à quelques microsecondes ou la réduire à une demi-heure, si vous le souhaitez. Pour cela, il suffit de changer le calcul des dernières lignes.
exemple exécuté:
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)
sortie:
2008-12-04 01:50:17
Une version minuscule.
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())),
)
Notez que les deux arguments start
et end
doivent être des objets datetime
. Si Vous avez plutôt des chaînes, il est assez facile de convertir. Les autres réponses indiquent des moyens de le faire.
C'est encore plus simple avec 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')
C'est très simple en utilisant le radar
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()
C'est une approche différente - ce genre de travail ..
from random import randint
import datetime
date=datetime.date(randint(2005,2025), randint(1,12),randint(1,28))
MEILLEURE APPROCHE
startdate=datetime.date(YYYY,MM,DD)
date=startdate+datetime.timedelta(randint(1,365))
Puisque Python 3 timedelta
prend en charge la multiplication avec des flottants, vous pouvez maintenant faire:
import random
random_date = start + (end - start) * random.random()
étant donné que start
et end
sont du type datetime.datetime
. Par exemple, pour générer une date/heure aléatoire le lendemain, procédez comme suit:
import random
from datetime import datetime, timedelta
start = datetime.now()
end = start + timedelta(days=1)
random_date = start + (end - start) * random.random()
Pour intégrer une solution à base de pandas, j'utilise:
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
Je l’aime bien, à cause des fonctionnalités de Nice pd.Timestamp
qui me permettent d’utiliser différents supports et formats. Considérez les quelques exemples suivants ...
Votre signature.
>>> 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)
Position aléatoire.
>>> 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)
Format différent.
>>> random_date('2008-01-01 13:30', '2009-01-01 4:50')
Timestamp('2008-11-18 17:20:19', tz=None)
Passer des objets pandas/datetime directement.
>>> random_date(pd.datetime.now(), pd.datetime.now() + pd.offsets.Hour(3))
Timestamp('2014-03-06 14:51:16.035965', tz=None)
Vous pouvez utiliser Mixer
,
pip install mixer
et,
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))
Juste pour en ajouter un autre:
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')
La gestion de jour nécessite quelques considérations. Avec 28, vous êtes sur le site sécurisé.
Le moyen le plus simple consiste à convertir les deux nombres en horodatages, puis à les définir comme limites minimales et maximales sur un générateur de nombres aléatoires.
Un exemple PHP rapide serait:
// 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);
}
Cette fonction utilise strtotime()
pour convertir une description datetime en un horodatage Unix et date()
pour définir une date valide à partir de l'horodatage aléatoire généré.
#!/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 __== '__main__':
import doctest
doctest.testmod()
Voici une réponse à la signification littérale du titre plutôt que le corps de cette question:
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)
Ce code est basé vaguement sur la réponse acceptée.
Voici une solution modifiée de l'approche d'Emyller qui renvoie un tableau de dates aléatoires à n'importe quelle résolution.
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))
Une partie de ce qui est bien avec cette approche est que np.datetime64
est vraiment doué pour contraindre les choses à des dates, vous pouvez donc spécifier vos dates de début/fin sous forme de chaînes, de dates/heures, d'horodatages de pandas ... pratiquement tout fonctionnera.
De nombreux algorithmes de conversion de date en nombre sont déjà disponibles dans de nombreux systèmes d'exploitation.
Pourquoi avez-vous besoin du nombre aléatoire? Généralement (en fonction de la langue), vous pouvez obtenir le nombre de secondes/millisecondes à partir d'une époque. Donc, pour une date aléatoire entre startDate et endDate, vous pouvez faire:
Sur la base de la réponse de mouviciel, voici une solution vectorisée utilisant numpy. Convertissez les dates de début et de fin en entiers, générez un tableau de nombres aléatoires entre elles et reconvertissez tout le tableau en dates.
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
Solution Pandas + 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 est la différence entre les horodatages en secondes (float). Il est ensuite utilisé pour créer un pandas temporisé entre 0 et dts, qui est ajouté à l'horodatage de départ.
En 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)
(besoin de la bibliothèque dateutil
de python - pip install python-dateutil
)
Conceptuellement, c'est assez simple. En fonction de la langue utilisée, vous pourrez convertir ces dates en un entier de référence de 32 ou 64 bits, représentant généralement les secondes depuis Epoch (1er janvier 1970), également appelé "heure Unix" ou millisecondes depuis une autre date arbitraire. Générez simplement un entier aléatoire de 32 ou 64 bits entre ces deux valeurs. Cela devrait être un one-line dans n'importe quelle langue.
Sur certaines plates-formes, vous pouvez générer une heure sous forme de double (la date est la partie entière, le temps la fraction est une implémentation). Le même principe s'applique sauf que vous avez affaire à des nombres à virgule flottante simple ou double précision («flottants» ou «doubles» en C, Java et autres langages). Soustrayez la différence, multipliez par un nombre aléatoire (0 <= r <= 1), ajoutez à l'heure de début et c'est fait.
Je l'ai fait pour un autre projet en utilisant aléatoire et le temps. J'ai utilisé un format général de temps, vous pouvez voir la documentation ici pour le premier argument de strftime (). La deuxième partie est une fonction random.randrange. Il retourne un entier entre les arguments. Changez-le pour les plages qui correspondent aux chaînes que vous souhaitez. Vous devez avoir de jolis arguments dans le tuple du deuxième article.
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))
Utilisez ApacheCommonUtils pour générer une longueur aléatoire dans une plage donnée, .__, puis créez une Date à partir de cette longueur.
Exemple:
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()));
}
C'est une méthode modifiée de @ (Tom Alsberg). Je l'ai modifié pour obtenir une date avec millisecondes.
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)
Exemple:
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())
Sortie: 2028/07/08 12:34:49.977963
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)))
Convertissez vos dates en horodatages et appelez random.randint
avec les horodatages, puis reconvertissez l'horodatage généré aléatoirement en une date:
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(
min(first_timestamp, second_timestamp), max(first_timestamp, second_timestamp)
)
return datetime.fromtimestamp(random_timestamp)
Ensuite, vous pouvez l'utiliser comme ça
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) # works the same
Si vous vous souciez des fuseaux horaires, vous devriez simplement utiliser la bibliothèque faker
, où j'ai volé ce code , comme le suggère déjà une réponse différente.