Newsgroup: it.comp.os.linux.sys
Titolo: "date" e la prima domenica del mese successivo...

Ciao a tutti,
sto cercando di farmi stampare quale sarà la prima domenica del prossimo mese... attraverso il comando "date"...
Supponendo di avere oggi la data (tirata avanti di un mese volutamente):
29/05/2011
per cui la prima domenica del nuovo mese dovrà essere:
05/06/2011
Ho provato con:
date -d "next month first monday" +%d/%m/%Y
30/06/2011
(sbagliato, sembrerebbe essere l' ultimo giorno di maggio, che tra l' altro non è neppure una domanica)
date -d "1 month first monday" +%d/%m/%Y
(idem come sopra)
date -d "now +next month first monday " +%d/%m/%Y
(idem come sopra)
leggendo le man e le info pages non ho cavato nulla di utile per capire dov'è l' errore...

sto cercando di farmi stampare quale sarà la prima domenica del prossimo mese... attraverso il comando "date"...
Con date, non si può. Stai fornendo DUE specifiche: "il prossimo mese" e
"la prima domenica".
Devi calcolarti innanzitutto il prossimo mese, e questo e' bene se *non*
lo fai con "date" (magari mi ricordo male, ma mi pare che il 30 gennaio,
se chiedi "next month", ti da' il 30 febbraio - ossia il 2 marzo).
Personalmente userei
	echo Feb,Mar,Apr,May,Jun,...,Dec,Jan | cut -f$(date +%m) -d,
Nel caso che tu sia a Dicembre devi ricordarti che
	YEAR=$( date +%Y )
	if [ "$MON" == "Jan" ]; then YEAR=$[ $YEAR + 1 ]; fi
A questo punto
	date +%w --date="$MON 1, $YEAR"
ti ritorna 0 se il primo giorno è domenica, 1 se è lunedì e così via. Se
il primo giorno è domenica la prima domenica è l'1; se è lunedì la prima
domenica sarà il 7, se è martedì il 6:
	w	desiderato
	0	1
	1	7
	2	6
	3	5
	4	4
	5	3
	6	2
Come dire che il risultato è 8, meno %w, modulo sette.
In totale
	MON=$( echo Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec,Jan | cut
-f$(date +%m) -d, )
	YEAR=$( date +%Y )
	if [ "$MON" == "Jan" ]; then YEAR=$[ $YEAR + 1 ]; fi
	WD=$( date +%w --date="$MON 1, $YEAR" )
	DAY=$[ ( 8 - $WD ) % 7 ]
La prima domenica sarà $DAY $MON $YEAR.
Locale permettendo ;-D
Leonardo S.E.&O.
-- 
Enough, enough!  But, stranger, ere we part,
Glancing farewell to each nefarious bier,
This warning would I beg you take to heart:
There is an end to e'en the worst career!

Con date, non si può.
Dovrei cercare di essere più onesto.
"Con date, non credo si possa, e io non ci sono mai riuscito".
Ecco, così è vero.
Leonardo che comunque garantiva solo freschezza, non verità


 "Con date, non credo si possa, e io non ci sono mai riuscito".
Altolà Hai letto i manuali di date della GNU?
info date:
|  ...
|  The fuzz in units can cause problems with relative items.  For
|  example, `2003-07-31 -1 month' might evaluate to 2003-07-01, because
|  2003-06-31 is an invalid date.  To determine the previous month more
|  reliably, you can ask for the month before the 15th of the current
|  month.  For example:
|  
|       $ date -R
|       Thu, 31 Jul 2003 13:02:39 -0700
|       $ date --date='-1 month' +'Last month was %B?'
|       Last month was July?
|       $ date --date="$(date +%Y-%m-15) -1 month" +'Last month was %B!'
|       Last month was June!
|  ...
Invece su altri sistemi la cosa può essere abbastanza complessa.

 dov'è l' errore...
Il tuo codice non calcola affatto la prima domenica del mese.
date -d "next mont" calcola la data tra trenta giorni. Se oggi è il 29 
maggio il risultato sarà 28 giugno. Se dai anche "next Monday" date
non calcola prima il prossimo lunedì e poi aggiunge un mese ed arrivi 
al 30 giugno, che è giovedì.
Ora vado, la soluzione stasera quando tornerò a casa.

Altolà Hai letto i manuali di date della GNU?
Sì, soprattutto la citazione all'inizio della pagina info. "Letto",
però, non "studiato"... sicché mi è certamente sfuggito un sacco di
cose.
Come dicevo all'OP, in genere cose di questo tipo le faccio con più
comandi: anche perché, se uno lo deve fare via script, di norma non
è una cosa dove contano i millisecondi.
E di soluzioni "ineleganti con molti comandi", ce ne sono molte; ne
ho proposta una senza pensarci troppo sopra[1], probabilmente la si
potrebbe migliorare parecchio usando la tua idea di usare il 15 del
mese dentro la stringa di formato.
Ma attendo curioso di vedere (e sgraffignare ;-)) la tua soluzione.
Leonardo
[1] il problema del locale m'e' baluginato solo dopo, ad esempio


 sto cercando di farmi stampare quale sarà la prima domenica del prossimo mese... attraverso il comando "date"...
ciao non date non saprei farlo ma con cal pipe sed si :-)
cal 6 2011 | sed -n '/^su/{:a; n; /^  /ba; s/^  *//;s/ .*//p;q;}'
(se usi la localizzazione italiana.. sostituisci "su" con "do").
Corrado Roberto
Fingerprint: 8FC8 05DE 2B53 A8AF 8B2B 6CBF AD23 C4D5 86FE 80BB

 (se usi la localizzazione italiana.. sostituisci "su" con "do").
Beh, ma se vale cal allora...
$ ncal -A1|tail -1|cut -b23
Fabio

 $ ncal -A1|tail -1|cut -b23
ma tu hai usato due pipe allora... bisogna fare 2 classifiche^^
comunque tornando a date, l'argomento %A mi sembra interessante a patto di incrementare il giorno fino a stampare domenica ed il mese per la data successiva.. mah io non ho mai avuto questa strana esigenza^^
ciao! :-)

 	DAY=$[ ( 8 - $WD ) % 7 ]
Se mi permetti di semplificare l'algoritmo, astraendomi anche dal locale...
$ date -d "$(date -d "next month" +%Y)-$(date -d "next month" +%m)-$[(8
- $(date -d "$(date -d "next month" +%Y)-$(date -d "next month" +%m)-01"
+%w)) % 7]" +%d/%m/%Y
... con l'unico vezzo di non aver usato variabili a scapito della
leggibilità e di qualche subshell in più :-)
Con rispetto
Fabio

 ma tu hai usato due pipe allora... bisogna fare 2 classifiche^^
Sě, ma tu dovresti scrivere qualcosa che trovi prima il mese :-)
Fabio

 +%w)) % 7]" +%d/%m/%Y
Ooops... mi ero scordato delle idiosincrasie di date(1) sulle date
relative. Ora dovrebbe andare meglio... nonostante sia sempre meno
comprensibile:
$ date -d "$(date -d "$(date +%Y-%m-15) +1 month" +%Y)-$(date -d \
"$(date +%Y-%m-15) +1 month" +%m)-$[(8 - $(date -d "$(date -d "$(date \
+%Y-%m-15) +1 month" +%Y)-$(date -d "$(date +%Y-%m-15) +1 month" \
+%m)-01" +%w)) % 7]" +%d/%m/%Y
Fabio

 Sì, ma tu dovresti scrivere qualcosa che trovi prima il mese :-)
e dell'anno.. se non si vuole arrivare a dicembre e incrementare verso un ipotetico 13 mese..
^^

 Ora vado, la soluzione stasera quando tornerò a casa.
Tra impegni vari e fine settimana del primo maggio rispondo solo ora.
Il problema on date è che la soluzione è molto artificiosa, dipende
dalle varie versioni di date e quindi non è portabile.
Ragionando con il date della GNU uno potrebbe provare:
date -d "next month first sunday"
che però non funziona. L'alternativa è usare un trucchetto per calco_
lare il primo giorno del mese e vedere in quale giorno della settima_
na cade per poi calcolare a mano la prima domenica:
$ primo=$(date -d "next month" +%Y/%m/1)
$ date -d "$primo + $((7 - $(date -d "primo" +%u) ))days"
dom giu  5 11:19:13 CEST 2011
$
Se ora vogliamo calcolare il primo mercoledì:
$ date -d "$primo + $(( (7 - $(date -d "$primo" +%w) + 3 ) % 7 ))days"
mer giu  1 00:00:00 CEST 2011
$
O il primo venerdì:
$  date -d "$primo + $(( (7 - $(date -d "$primo" +%w) + 5 ) % 7 ))days"
ven giu  3 00:00:00 CEST 2011
$
PS Si sono usati anche dei calcoli atitmentici che funzionano con bash
kshell e poche altre shell e questo rend la soluziono ancora meno 
portabile.

Addì  domenica 1 maggio 2011 02:04 bio scrisse:

Essenzialmente è la soluzione proposta da me con molte inutili
complicazioni. Riguardo alle cosiddette idiosincrasie di date, i 
problemi nascono quando si calcolano dei riferimenti al mese 
precedente.

 precedente.
Tu avrai, lo sento, notato un abuso di subshell, peraltro annunciato.
E financo l'inutile concatenamento laddove con profitto s'userebbe la 
stringa di formato. Ma e' solo per divertimento, il codice offuscato. 
Certo questo mio non brilla, è vero, per maestria e per ardimento, ma 
suvvia, non fare sempre l'imbronciato.
Fabio

 suvvia, non fare sempre l'imbronciato.
Perché imbronciato? No è solo che ho avuto il mio da fare ma
allo stesso tempo non volevo è privare l'opener di una soluzione 
nè prendermi il merito di una soluzione già postata.
Certo a volte capita a più persone di postare la stessa soluzione 
contemporaneamente o a breve distanza; capita, non facciamo 
la gara a chi risponde prima, e non si bada più di tanto a ciò ma
dopo quattro giorni...

 dopo quattro giorni...
Ti secca di averla postata così in ritardo? Mica ti ha pagato :-) 
E poi il tuo post delle 11:45, anche se è arrivato dieci ore dopo 
il mio, ha comunque senso: la soluzione di leo era "lunga", la mia 
era più un gioco e per essere inserita in uno script senza che ti 
ridessero dietro andava quanto meno "condensata"... la tua, anche 
se è arrivata per ultima, ha il vantaggio di essere pronta all'uso: 
all'op basta un copia e incolla, e via.
'notte
Fabio

 niente di _ancora_ piu' stupido :-D
eh Leonardo... fossero tutti come te il mondo di usenet sarebbe
sicuramente migliore :-)
E ... fra l'altro ... tu sei pure preparato, quindi il commento è
stato quantomeno ingeneroso.

stato quantomeno ingeneroso.
Bof, alla fine mi pare che, per varie strade e per diversi porti,
siamo tutti arrivati press'a poco allo stesso metodo, ovvero fare
a pezzettini la data del "prossimo mese" e di li' calcolare quale
giorno sia la "prima domenica".
Delle implementazioni, la mia era senz'altro la più rozza (guarda
solo al problema del locale).
Nel frattempo m'era venuta in mente anche quest'altra alternativa
- rigorosamente non testata ;-)
    cal -3 | cut -b 46- | grep ^[1-7] | head -n 1 | cut -b1
Leonardo


Rieccomi,
ho partorio questo script che sembra essere funzionante (le date mi servono in formato MM/GG/AAAA). 
#!/bin/bash
CURRENT_MONTH_N=$(date +%m)
CURRENT_DAY_N=$(date +%d)
CURRENT_YEAR=$(date +%Y)
# SE IL GIORNO CORRENTE E' > DI 7  CERCO LA PRIMA DOMENICA NEL MESE SUCCESSIVO
#
if [[ $CURRENT_DAY_N -gt 7 ]]; then
        #SE E' DICEMBRE INCREMENTO ANNO E VADO A GENNAIO
        if [[ $CURRENT_MONTH_N == 12 ]]; then
                SET_DATE_YEAR=$(( $CURRENT_YEAR + 1))
                SET_DATE_MONTH=1
        else
        #ALTRIMENTI MANTENGO ANNO CORRENTE E' INCREMENTO SOLO IL MESE
                SET_DATE_YEAR=$CURRENT_YEAR
                SET_DATE_MONTH=$(( $CURRENT_MONTH_N + 1 ))
        fi
        # SE IL MESE E' COMPOSTO DA UNA SOLA CIFRA: ANTEPONGO UNO ZERO
        if [[ ${#SET_DATE_MONTH} = 1 ]]; then
                SET_DATE_MONTH=0$SET_DATE_MONTH
        fi
        # CERCO FINO A CHE IL RISULTATO NON E dom
        SET_DATE_DAY_N=1
        while [[ $QUERY_DATE_T != "dom" && $QUERY_DATE_T != "sun" ]]
        do
                QUERY_TEXT=$SET_DATE_MONTH/0$SET_DATE_DAY_N/$SET_DATE_YEAR
                QUERY_DATE_T=$(date --date="$QUERY_TEXT" +%a)
                SET_DATE_DAY_N=$(( $SET_DATE_DAY_N + 1 ))
        done
        FIRST_SUNDAY=$QUERY_TEXT
        FIRST_MONDAY=$(date --date="$FIRST_SUNDAY tomorrow" +%m/%d/%Y)
else
# ALTRIMENTI E' LA PROSSIMA DOMENICA
        FIRST_SUNDAY=$(date --date=\"next sunday\" +%m/%d/%Y)
        FIRST_MONDAY=$(date --date=\"next monday\" +%m/%d/%Y)
fi
echo $FIRST_SUNDAY
echo $FIRST_MONDAY
Ci sono eccezioni che non ho considerato?

Subito beccata l' eccezione, script corretto:
#!/bin/bash
CURRENT_MONTH_N=$(date +%m)
CURRENT_DAY_N=$(date +%d)
CURRENT_DAY_T=$(date +%a)
CURRENT_YEAR=$(date +%Y)
# SE IL GIORNO CORRENTE E' > DI 7 O E DOMENICA CERCO LA PRIMA DOMENICA NEL MESE SUCCESSIVO
#
if [[ $CURRENT_DAY_N -gt 7 || $CURRENT_DAY_T="dom" || $CURRENT_DAY_T="sun" ]]; then





        FIRST_MONDAY=$(date --date="next sunday tomorrow" +%m/%d/%Y)
