他の2つの日付の間にランダムな日付を生成する


137

他の2つの日付の間にある必要があるランダムな日付をどのように生成しますか?

関数のシグネチャは次のようになります。

random_date("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


現時点での質問の提示方法では、日付または時刻のみをランダムにするかどうかが明確ではありません。あなたの例はあなたが時間を探していることを示唆しています。2つの日付の間にある必要がある場合は、これまでの回答をニーズに合わせて変更し、終了時間と開始時間を除外することができます。最後に、受け入れられたものなど、ほとんどの回答では、intに切り捨てられているため、コードはendtimeを除くdatetimeを出力します。回答の終わりを含む可能性のある時間を生成するには、コードをptime = stime + prop * (etime - stime) + 0.5
tortal

回答:


149

両方の文字列をタイムスタンプ(ミリ秒、秒、時間、日など、選択した解像度で)に変換し、前の時刻から後の時刻を減算し、乱数(で配布されていると想定range [0, 1])にその差を掛けて、再度追加します以前のもの。タイムスタンプを日付文字列に変換し直すと、その範囲の時間がランダムになります。

Pythonの例(出力は、0パディング以外はほとんど指定した形式です-アメリカの時間形式の規則を非難します):

import random
import time

def str_time_prop(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 random_date(start, end, prop):
    return str_time_prop(start, end, '%m/%d/%Y %I:%M %p', prop)

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

このアプローチでは、1970
。– Cmbone

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

精度は秒です。必要に応じて、精度をマイクロ秒まで上げるか、たとえば30分に下げることができます。そのためには、最後の行の計算を変更します。

実行例:

from datetime import datetime

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

3
その場合のstart変数の使用は完全に正しいです。コードで私が目にする唯一の問題はseconds、結果の属性の使用ですdelta。間隔全体の合計秒数は返されません。代わりに、「時間」コンポーネントからの秒数(0〜60の間)です。timedeltaオブジェクトが持っているtotal_seconds代わりに使用するメソッドを、。
emyller

7
@emyller:いいえ、使用(delta.days * 24 * 60 * 60) + delta.secondsしているので合計秒数になります。このtotal_seconds()メソッドはpython 2.7で新しく追加されたもので、2009年に質問に回答した時点では存在していませんでした。Python 2.7を使用している場合は、代わりにそれを使用する必要がありますが、コードはそのまま正常に動作します。
nosklo

2.7-にはこのメソッドが存在しないことに気づきませんでした。私はtimedeltaオブジェクトが基本的に日数と秒数で構成されていることを確認したので、あなたは正しいです。:-)
emyller

@emyller:完全を期すために、timedeltaオブジェクトは日、秒、マイクロ秒で構成されています。上記のランダムな日付生成コードの精度は最大で数秒ですが、回答で述べたように、変更される可能性があります。
nosklo

83

小さなバージョン。

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オブジェクトでなければならないことに注意してください。代わりに文字列がある場合、変換はかなり簡単です。他の回答は、そうするためのいくつかの方法を示しています。


54

回答を更新しました

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

3
fakerモジュールを提案することへの賛成投票..私はプロファイルの生成に使用していましたが、日付ユーティリティを使用していませんfakerはテスト中に非常に優れたモジュールです。
Gahan

この形式で出力を取得していますが、このdatetime.date(2039, 3, 16)ような出力が必要です2039-03-16。どうやってするか?
Ayush Kumar

つまり、あなたは文字列が必要ですか?非常に簡単に(ちょうどそれに応じてフォーマットします): fake.date_between(start_date='today', end_date='+30y').strftime('%Y-%m-%d')
Artur Barseghyan、2018年

1
あなたがそれをインストールする必要がある場合でも、信じられないほどのライブラリを使用するための賛成票を投じてください。これにより、実装の複雑さが本質的に4行に削減されます。
Blairg23 2018年

1
@ KubiK888:確かに、私のアップデートの答えを見てください。start_dateを明示的に指定するだけです。
Artur Barseghyan

24

これは別のアプローチです-そのような作品..

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

1
最初のアプローチは、29日、30日または31日に終了日付を選択することはありませんし、場合年は366日、すなわちあるときに、あなたの第二のアプローチは、うるう年を考慮していないstartdate、これを+ 1年がうるう年で12月31日を通過しますコードは、ちょうど1年後に同じ日付を選択することはありません。どちらの方法でも、開始日と将来の年数を指定できるだけですが、質問では2つの日付を指定することについて尋ねていましたが、私の意見では、これはより便利なAPIです。
ボリス

15

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

私が使用するパンダベースのソリューションでチップするには:

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)

そして、どのようにしてエレガントな(つまり、要素ごとに関数を繰り返すことなく)ランダムな日時シリーズを作成しますか?
dmvianna 2014年

まあ、多分delta値の配列を生成するために関数を修正して、それらを一度にタイムスタンプにマップすることは可能かもしれません。個人的には、しかし、私はただのようなことをしたいと思いpd.Series([5] * 10, [random_date('2014-01-01', '2014-01-30') for i in range(10)])ます。
metakermit 2014年

3

この質問の本文ではなく、タイトルの文字通りの意味に対する回答を次に示します。

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)

このコードは、受け入れられた回答に大まかに基づいています。


最後の2行目を変更して、範囲を限定的にするptime = random.randint(stime, etime)ためrandint、多少正確になります。
ボリス

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

1
構文がないように注意してください上記を行う方法を、少し変更されていますが、Djangoのオブジェクトは、ランダムな日付がそうのように満たされています:client = mixer.blend(Client, date=mixer.RANDOM)
tutuDajuju

@tutuDajuju:クライアントは何を表していますか?
Nima Soroush、2015

彼らのドキュメントによると、それはDjango、SQLAlchemy、またはMongoengineモデルクラスになる可能性があります。
tutuDajuju 2015

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

2

日付をタイムスタンプに変換し、タイムスタンプを使用して呼び出します。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

別の答えがすでに示唆しているように、タイムゾーンに関心がある場合は、このコードをから盗んだライブラリdate_time_between_datesから使用する必要があります。Faker


1
  1. 入力日付を数値に変換します(int、float、使用に最適なもの)
  2. 2つの日付番号の間の数値を選択してください。
  3. この数値を日付に変換します。

日付を数値に変換するための多くのアルゴリズムが、多くのオペレーティングシステムですでに利用可能です。


1

何のために乱数が必要ですか?通常(言語によって異なります)、日付からエポックから秒/ミリ秒数を取得できます。したがって、startDateとendDateの間のランダムな日付の場合、次のようにすることができます。

  1. startDateとendDateの間の時間をミリ秒単位で計算します(endDate.toMilliseconds()-startDate.toMilliseconds())
  2. 0と1で取得した数の間の数を生成する
  3. 時間オフセット= startDate.toMilliseconds()+ 2で取得した数値で新しい日付を生成します

1

これを行う最も簡単な方法は、両方の数値をタイムスタンプに変換してから、これらを乱数ジェネレータの最小および最大の境界として設定することです。

簡単な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()生成されたランダムなタイムスタンプから有効な日付を作成するために使用します。


誰かがそれをPythonで書くことができればそれは役に立ちます。
quilby 2009

1

別のものを追加するだけです:

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

これは、任意の解像度でランダムな日付の配列を返すエミラーのアプローチから変更されたソリューションです

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

このアプローチの良い点の1つnp.datetime64は、日付に強制的に変換するのに優れていることです。そのため、開始/終了日を文字列、日時、パンダタイムスタンプとして指定できます。ほとんど何でも機能します。


0

概念的には非常に単純です。使用している言語に応じて、これらの日付をいくつかの参照32ビットまたは64ビット整数に変換できます。これは通常、エポック(1970年1月1日)からの秒数を表し、「Unix時間」または他の任意の日付からのミリ秒とも呼ばれます。これらの2つの値の間に32ビットまたは64ビットのランダムな整数を生成するだけです。これは、あらゆる言語のワンライナーである必要があります。

一部のプラットフォームでは、時刻をdoubleとして生成できます(日付は整数部、時刻は小数部が1つの実装です)。単精度または倍精度の浮動小数点数(C、Java、およびその他の言語では「floats」または「doubles」)を扱う場合を除いて、同じ原理が適用されます。差を引き、乱数(0 <= r <= 1)を掛け、開始時間に加算して完了します。


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


0

ApacheCommonUtilsを使用して、指定された範囲内でランダムなlongを生成し、そのlongからDateを作成します。

例:

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

}


1
質問には「python」というタグが付けられています
David Marx

0

私はランダムと時間を使用して別のプロジェクトのためにこれを作りました。strftime()の最初の引数については、ここのドキュメントを参照してください。2番目の部分は、random.randrange関数です。引数の間の整数を返します。希望する文字列に一致する範囲に変更します。あなたは2番目の薬のタプルに素敵な議論があるはずです。

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

0

パンダ+ 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)。次に、0からdtsまでのパンダタイムデルタを作成するために使用され、開始タイムスタンプに追加されます。


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

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


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

紹介する


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

0

代替使用して2つの日付の間のランダムな日付を作成する方法np.random.randint()pd.Timestamp().valueおよびpd.to_datetime()持ちますfor loop

# Import libraries
import pandas as pd

# Initialize
start = '2020-01-01' # Specify start date
end = '2020-03-10' # Specify end date
n = 10 # Specify number of dates needed

# Get random dates
x = np.random.randint(pd.Timestamp(start).value, pd.Timestamp(end).value,n)
random_dates = [pd.to_datetime((i/10**9)/(60*60)/24, unit='D').strftime('%Y-%m-%d')  for i in x]

print(random_dates)

出力

['2020-01-06',
 '2020-03-08',
 '2020-01-23',
 '2020-02-03',
 '2020-01-30',
 '2020-01-05',
 '2020-02-16',
 '2020-03-08',
 '2020-02-09',
 '2020-01-04']
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.