The official Fatica Labs Blog! RSS 2.0
# Wednesday, 16 June 2010

Probabilmente vi sarà capitato di dovere eseguire qualche azione all’interno del vostro software dipendentemente da trigger innescati da data e/o ora. Per esempio un certo processo non si scatena del week-end, oppure un altro processo deve partire solo a mezzanotte etc etc. Quando queste cose non siano attuabili esternamente con il task scheduler di sistema, sarebbe bello poter avere una libreria pronto uso in .NET. Ebbene questa libreria c’è, ed è il parser di espressioni Cron che trovate qui. Lungi dall’essere un concetto moderno, si tratta di un modo di esprimere range temporali tramite una stringa che arriva da Unix. Oggi chiamiamo una cosa simile “Domain Specific Language”, ma tant’è il concetto è il medesimo. Lungi anche dall’ essere originale il concetto in .NET, la libreria che propongo è una estrapolazione di codice dalla più completa e complessa libreria Quartz.NET, a sua volta un porting della libreria Java Quartz. Se non volete introdurre troppa complessità al vostro deploy aggiungendo una nuova libreria, potete “grabbare” le classi dalla dll di Cron.NET ( sono tre file… ) e compilarli con il vostro progetto, ed avrete a disposizione tutta la potenza delle espressioni Cron ;).

Già, ma come funzionano le espressioni Cron ? Facciamo un paio di esempi:

"* * 10-11 L * ?" = questo trigger è valido l’ultimo del mese dalle 10-11

"* * * ? * MON-FRI" = questo trigger è valido tutti i giorni, a tutte le ore, eccetto il week end.

Ok, questo da l’idea delle potezialità della cosa, ma ovviamente serivirebbe una più estesa…

Documentazione

Una espressione Cron è composta da 6 campi obbligatori, più uno opzionale. Il significato dei campi è schematizzato nella tabella qui sotto:

Campo   Valori permessi   Caratteri speciali ammessi
Secondi   0-59   , - /
Minuti   0-59   , - /
Ore   0-23   , - /
Giorno del mese   1-31   , - ? / L W C
Mese   1-12 or JAN-DEC   , - /
Giorno della settimana   1-7 or SUN-SAT   , - ? / L #
Anno ( Opzionale )   vuoto, 1970-2099   , - /

 

Il carattere jolly ‘*’ può sempre essere usato con il significato di “tutti i valori”, per esempio se metto ‘*’ nel campo minuti significa tutti i minuti.

Il carattere ‘?’ può essere usato solo come Giorno del mese o giorno della settimana. Significa “nessun valore in particolare” e serve quando devo fissare l’altro. Se per esempio fisso il giorno della settimana metterò ‘?’ nel giorno del mese, e viceversa.

Il carattere ‘-‘ lo utilizzo quando voglio specificare un range: per esempio 10-12 nel campo ora significa dalle 10 a tutte le 12.

Uso invece la ‘,’ quando voglio specificare singolarmente più valori possibili: JAN,MAR significa il mese di Gennaio e di Marzo, ma non Febbraio ( e, ovviamente, non tutti gli altri ).

Per specificare dei periodi utilizzo ‘/’: per esempio se metto 0/15 nel campo secondi, significa “ogni 15 secondi”: sarà attivo il trigger quindi ai secondi 15,30,45 etc etc.

Il carattere speciale ‘L’ significa ultimo. Nel campo mese significa semplicemente l’ultimo giorno del mese (30/31/28 o 29 ) in modo concorde con il mese / anno bisestile. Nel campo settimana significa semplicemente 7 ( cioè Sabato ), ma se preceduto da un numero significa “l’ultimo xxxx del mese”. Per esempio se scrivo 6L significa l’ultimo Venerdì del mese.

Il carettere ‘W’ può essere specificato solo nel campo giorno del mese, preceduto da un solo carattere, e significa “il giorno lavorativo più vicino a”. Per esempio se scrivo 1W significa il giorno lavorativo più vicino al primo del mese. Se scrivo LW significa l’ultimo giorno lavorativo del mese.

Per ultimo il carattere ‘#’, utilizzabile solo nel giorno della settimana, indica l’ennesimo xxxx del mese. Per esempio, se mi interessa il terzo venerdì del mese, scriverò 6#3.

Per utilizzare una cron expression basta creare un istanza dell’ogegtto CronExpression, passando la stringa sul costruttore. Ecco un esempio:

   1:          [Test]
   2:          public void LastOfTheMonth()
   3:          {
   4:              var exp = new CronExpression("* * * L * ?");
   5:              Assert.IsTrue(exp.IsSatisfiedBy(new DateTime(2000, 1, 31)));
   6:              Assert.IsTrue(exp.IsSatisfiedBy(new DateTime(2000, 2, 29)));
   7:              Assert.IsFalse(exp.IsSatisfiedBy(new DateTime(2000, 2, 28)));
   8:          }
Wednesday, 16 June 2010 16:52:39 (GMT Daylight Time, UTC+01:00)  #    Comments [0] - Trackback
Cron | Programmin | Recipes

My Stack Overflow
Contacts

Send mail to the author(s) E-mail

Tags
profile for Felice Pollano at Stack Overflow, Q&A for professional and enthusiast programmers
About the author/Disclaimer

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2017
Felice Pollano
Sign In
Statistics
Total Posts: 157
This Year: 0
This Month: 0
This Week: 0
Comments: 124
This blog visits
All Content © 2017, Felice Pollano
DasBlog theme 'Business' created by Christoph De Baene (delarou) and modified by Felice Pollano