Newsgroup: it.comp.lang.perl
Titolo: Come generare date random ma valide

Ho bisogno di generare casualmente delle date valide dal 1-1-1930 al
1-1-1993.
Ovviamente i 30 Febbraio non vanno etc etc ...
Chi mi puo consigliare ?
Forse esiste una funzione che genera una data da un numero e dandogli in
pasot un numero random compreso nell'intervallo che mi serve ce la potrei
fare ?
Grazie mille. Bob
PS Sono un principiante !

 Chi mi puo consigliare ?
   I moduli della collezione Date::Calc [1] dovrebbero consentirti di 
convertire le differenze tra date in secondi. Normalizzando queste 
differenze, potrai, per mezzo delle usuali funzioni di generazione di 
numeri casuali, ottenere cio` che ti occorre.
[1] 
http://www.cpan.org/modules/by-module/Date/Date-Calc-5.3.readme
     Leggi attentamente la documentazione a corredo: la libreria
     e` particolarmente vasta.
-- 
Alla prossima,
Marco



Velocemente:
Calcoli i timestamp relativi al 1-1-1930 e 1-1-1993.
Prendi un numero casuale (pseudo-random, of course) tra i due
e riconverti in data.
Ingredienti: rand e la libreria POSIX ;-)
Altrimenti usi librerie per la gestione delle date che ti permettono
di applicare metodi più eleganti e precisi
	- Enrico

 Calcoli i timestamp relativi al 1-1-1930 e 1-1-1993.
   Il problema e` che il timestamp di una data si calcola in base ad un 
valore di riferimento che, nel caso del Perl, e` l'Epoch (1970-01-01 
0:00:00 GMT), mentre l'OP e` interessato a date precedenti. Non so (ma 
sono interessato a saperlo) se si possa aggirare questo inconveniente 
senza ricorrere a moduli di estensione.
-- 
Alla prossima,
Marco

 
by
	- E
PS: Vale cmq l'algoritmo sostitunendo il termine 'giorno' a 'timestamp'
utilizzando funzioni e metodi di moduli quali Date::Calc.

 ha scritto nel messaggio
news:20030130165948....@sorcinelli.it...


ehm... mi permetto:
if (($anno % 4 == 0) && ($anno % 100 != 0) || ($anno % 400 == 0)){
do_bisestile();
}
no? ;-)
ciao
lorenzo (nuovo arrivato)


 un altro per il giorno,
BBbbravo! Per una volta devo farti i complimenti per farla semplice, perché
il metodo è rapido e intelligente! :-)
Ma non te l'hanno suggerito? :-))))
--
perl -MLWP::Simple -e "getprint(' 
http://perl.4pro.net
 ')"

 Ma perché la fate sempre difficile ?
   Perche` il modulo Date::Calc e` una fonte (quasi) inesauribile di 
cose che potrebbero risultare utili in futuro e, quindi, questa potrebbe 
essere per l'OP l'occasione buona per iniziare a conoscerlo.
   In quanto alla difficolta`, non la vedo. Con Delta_Days si calcola il 
valore di normalizzazione per la rand e con Add_Delta_Days si aggiungono 
i giorni pseudo-casuali, senza doversi inventare nulla per evitare il 29 
Febbraio quando non dovrebbe esserci o eventuali 31 Giugno.
<code>
	use Date::Calc qw(Add_Delta_Days Delta_Days);
	use strict;
	my $norm=Delta_Days
	    1930,1,1
	    1993,1,1
	;
	srand;
	my $rdays=rand $norm;
	my ($ryear,$rmonth,$rday)=Add_Delta_Days 1930,1,1,$rdays;
</code>
-- 
Alla prossima,
Marco


A parte che mi pare una soluzione un po' troppo su misura (la formula per
l'anno bisestile, č vero che va bene per l'intervallo considerato, ma č, in
generale, sbagliata), e che l'algoritmo andrebbe perfezionato per evitare
altre date imbarazzanti, come il 31 novembre, aprile, giugno e settembre,
credo che cosě ci si discosti dalla distribuzione casuale (in che misura,
non ho voglia di calcolarlo, e se lo scarto č accettabile puň dirlo solo
chi ha formulato la domanda).
Usare un qualunque modulo per il trattamento di date, per calcolare il
giorno giuliano o la differenza fra le due date, non č davvero piů
complicato che far funzionare per bene un algoritmo autocostruito, e
fornisce una soluzione piů precisa e piů generale.
Ciao.

altre date imbarazzanti, come il 31 novembre, aprile, giugno e settembre,
Così potrebbe anche funzionare:
    sub bisestile {
      my($y)=@_;
      return 0 unless $y % 4 == 0;
      return 1 unless $y % 100 == 0;
      return 0 unless $y % 400 == 0;
      return 1;
    }
    sub gen {
     my ($anno_inizio, $anno_fine) = @_;
     my $anni = $anno_fine - $anno_inizio;
     my $anno = int(rand($anni)) + $anno_inizio;
     my $mese = int(rand(11)) + 1;
     my $giorno;
     if ($mese == 2) {
             if (bisestile($anno)) {
                     $giorno = int(rand(28)) +1;
             } else {
                     $giorno = int(rand(27)) + 1;
             }
     } elsif ($mese == 11 ||
               $mese == 4 ||
               $mese == 6 ||
               $mese == 9) {
             $giorno = int(rand(29)) + 1;
     } else {
             $giorno = int(rand(30)) + 1;
     }
     return $giorno, $mese, $anno;
    }
Sempre che non abbia commesso qualche banale errore (che è il motivo per
cui una soluzione preconfezionata, già opportunamente testata da autore e
utilizzatori, se esiste, è in genere preferibile).
Ciao.

     }
[cut]
.. va beh, qui i nuovi arrivati non li salutate... ;-)
ciao a tutti
lorenzo

.. va beh, qui i nuovi arrivati non li salutate... ;-)
Per la verità, io ho porto il mio consueto, brevettato, omaggio: un
grazioso cenno d'inchino con la testa di 50° 10', accompagnato da un
rispettoso abbassamento delle palpebre per 0.75 secondi (così saluto
chiunque, da mia madre all'ultimo arrivato).
Non è colpa mia se il presente mezzo non è in grado di trasmettere il
gesto.
Il codice che riporti l'ho preso pari pari da Date::Manip (solo i nomi sono
stati cambiati, per proteggere gli innocenti).
Ciao.

[cut]
(solo i nomi sono stati cambiati, per proteggere gli innocenti).
[cut]
?????
si tratta della traduzione in perl della formula... cosa vorresti dire
altrimenti?
tra parentesi fa uso di un solo IF articolato logicamente al posto di più
unless...
mi fermo qui, probabilmente del tutto.
Ah... ringrazio sentitamente del cenno sornione :-DD
lorenzo

unless...
Credo che le due versioni siano, in esecuzione, sostanzialmente identiche,
considerando il short-cut delle espressioni logiche, sicché la preferenza è
estetica.
Ciao.

Grazie a tutti.
Alla fine ho deciso di fare cosi':
use Time::JulianDay;
$jdStart = julian_day(1950,  1,  1) ; # Earliest date in desired range
$jdEnd   = julian_day(1993, 12, 31) ; # Latest ...
$jd = int( rand ($jdEnd - $jdStart) ) + $jdStart ; # Pick random day
($year, $month_1_to_12, $day) = inverse_julian_day($jd) ;
Funziona molto bene.
Ciao Bob.