C #의 임의 날짜


141

1995 년 1 월 1 일과 현재 날짜 사이에 임의의 날짜를 생성하는 간결하고 현대적인 C # 코드를 찾고 있습니다.

Enumerable을 사용하는 솔루션을 생각하고 있습니다 .Range는 어떻게 든 간결하게 만들 수 있습니다.


답변 범위 사이의 임의의 날짜 시간 -하지 통합 출력 /하려면 날짜 매개 변수에서와 도우미 방법이있다
마이클 Freidgeim에게

답변:


241
private Random gen = new Random();
DateTime RandomDay()
{
    DateTime start = new DateTime(1995, 1, 1);
    int range = (DateTime.Today - start).Days;           
    return start.AddDays(gen.Next(range));
}

반복적으로 호출 될 경우 성능을 향상 시키려면 함수 외부startand gen(및 가능하면 range) 변수를 작성하십시오 .


1
랜덤은 의사 랜덤입니다. 정말로 무작위가 필요한 경우 System.Security.Cryptography 네임 스페이스에서 RNGCryptoServiceProvider를 사용해보십시오.
tvanfosson

고마워요 tvanfosson. 이 문제에는 의사 난수이면 충분합니다.
유다 가브리엘 희망 고

5
실제로 Random은 인스턴스를 잠시 동안 유지하고 값을 계속 가져 가지 않는 한 특히 의사 난수는 아닙니다.
David Mitchell

2
이것이 프로덕션 코드가 아닌 샘플에 불과한 이유입니다.
Joel Coehoorn

1
그렇습니다, 그것은 저에게 효과적입니다. 내 실제 코드는 메서드 자체 외부에 임의 인스턴스가 있습니다.
유다 가브리엘 히 망고

25

이것은 매우 최적화 된 버전을 만드는 것에 대한 Joel의 의견에 대한 약간의 대답입니다. 임의의 날짜를 직접 반환하는 대신 임의의 날짜를 만들기 위해 반복적으로 호출 할 수있는 생성기 함수를 반환하지 않는 것이 좋습니다.

Func<DateTime> RandomDayFunc()
{
    DateTime start = new DateTime(1995, 1, 1); 
    Random gen = new Random(); 
    int range = ((TimeSpan)(DateTime.Today - start)).Days; 
    return () => start.AddDays(gen.Next(range));
}

이것이 어떻게 유익한 지 설명 할 수 있습니까? 대신 클래스 멤버로 시작, 생성 및 범위를 지정할 수 없습니까?
Mark A. Nicolosi

그들은 할 수 있었고이 경우에는 가능합니다. 후드 아래에서 이것은 시작, 생성 및 범위를 멤버로 포함하는 성가신 어휘 폐쇄를 생성합니다. 이것은 더 간결합니다.
JaredPar

좋은 기능, 난 아무도 그것을 사용하지 않기를 바라고 있어요 :for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
Aidiakapi

2
이 기능은 어떻게 사용됩니까? 누군가 설명해 주시겠습니까? 어떻게 부를 수 있습니까?
Burak Karakuş

2
@ BurakKarakuş : 당신은 먼저 공장을 얻는다 : var getRandomDate = RandomDayFunc();그리고 당신은 임의의 날짜를 얻기 위해 그것을 호출한다 : var randomDate = getRandomDate();이것이 Joel의 대답보다 더 유용하기 위해서는 getRandomDate를 재사용해야한다는 점.
Şafak Gür

8

@Joel Coehoorn의 답변을 취하고 조언을 변경했습니다. 변수를 메소드에서 꺼내고 클래스에 모두 넣습니다. 또한 이제 시간도 임의적입니다. 결과는 다음과 같습니다.

class RandomDateTime
{
    DateTime start;
    Random gen;
    int range;

    public RandomDateTime()
    {
        start = new DateTime(1995, 1, 1);
        gen = new Random();
        range = (DateTime.Today - start).Days;
    }

    public DateTime Next()
    {
        return start.AddDays(gen.Next(range)).AddHours(gen.Next(0,24)).AddMinutes(gen.Next(0,60)).AddSeconds(gen.Next(0,60));
    }
}

그리고 콘솔에 100 개의 임의의 DateTime을 쓰는 데 사용하는 방법의 예 :

RandomDateTime date = new RandomDateTime();
for (int i = 0; i < 100; i++)
{
    Console.WriteLine(date.Next());
}

왜 Random ()을 두 번 작성합니까? 일단 클래스 변수 gen 선언과 c-tor에서 다른 시간에?
픽셀

예, 한 번이면 충분합니다. 나는 그것을 고쳤다.
prespic

1
그것은 초 단지 하나의 난수를 생성하고 시작 날짜에 그것을 추가 할 네 배 빠른 관하여 : range = (int)(DateTime.Today - start).TotalSeconds;return start.AddSeconds(gen.Next(range));.
Jurgy

5

대체 최적화를 제시하려면 반복자를 사용할 수도 있습니다.

 static IEnumerable<DateTime> RandomDay()
 {
    DateTime start = new DateTime(1995, 1, 1);
    Random gen = new Random();
    int range = ((TimeSpan)(DateTime.Today - start)).Days;
    while (true)
        yield return  start.AddDays(gen.Next(range));        
}

다음과 같이 사용할 수 있습니다.

int i=0;
foreach(DateTime dt in RandomDay())
{
    Console.WriteLine(dt);
    if (++i == 10)
        break;
}

1
반복자와 생성기 함수 사이에서 고려해야 할 사항은 반복자 솔루션이 IDisposable 값을 생성한다는 것입니다. 이로 인해 발신자는 GC에 파이널 라이저가있는 가격을 처분하거나 지불해야합니다. 발전기는 폐기 할 필요가 없습니다
JaredPar

2
@JaredPar, 그건 옳지 않습니다. 유형이 IDisposable을 구현한다고해서 그것이 최종화 가능한 것은 아닙니다.
Drew Noakes

3

고정 날짜 개체 (1995 년 1 월 1 일)로 시작하고 AddDays를 사용하여 임의의 일 수를 추가하십시오 (분명히 현재 날짜를 초과하지 않도록주의하십시오).


고마워 Friol. 무작위로 전달되는 수를 제한하는 방법을 물어 보려고했습니다. Joel은 코드 샘플로 예제를 게시 했으므로 응답을 답변으로 표시하겠습니다.
유다 가브리엘 희망 고

0

나는 게임에 조금 늦었지만 여기에 잘 작동하는 솔루션이 있습니다.

    void Main()
    {
        var dateResult = GetRandomDates(new DateTime(1995, 1, 1), DateTime.UtcNow, 100);
        foreach (var r in dateResult)
            Console.WriteLine(r);
    }

    public static IList<DateTime> GetRandomDates(DateTime startDate, DateTime maxDate, int range)
    {
        var randomResult = GetRandomNumbers(range).ToArray();

        var calculationValue = maxDate.Subtract(startDate).TotalMinutes / int.MaxValue;
        var dateResults = randomResult.Select(s => startDate.AddMinutes(s * calculationValue)).ToList();
        return dateResults;
    }

    public static IEnumerable<int> GetRandomNumbers(int size)
    {
        var data = new byte[4];
        using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider(data))
        {
            for (int i = 0; i < size; i++)
            {
                rng.GetBytes(data);

                var value = BitConverter.ToInt32(data, 0);
                yield return value < 0 ? value * -1 : value;
            }
        }
    }

0

간단한 입력 매개 변수를 기반으로 임의의 날짜를 문자열로 반환하는 작은 메서드입니다. 위 답변의 변형을 기반으로 작성되었습니다.

public string RandomDate(int startYear = 1960, string outputDateFormat = "yyyy-MM-dd")
{
   DateTime start = new DateTime(startYear, 1, 1);
   Random gen = new Random(Guid.NewGuid().GetHashCode());
   int range = (DateTime.Today - start).Days;
   return start.AddDays(gen.Next(range)).ToString(outputDateFormat);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.