解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
10.53 KiB
X
# Cron±í´ïʽ ## ¸ÅÊö `NewLife.Threading.Cron` ÊÇÒ»¸öÇáÁ¿¼¶µÄ Cron ±í´ïʽ½âÎöºÍÆ¥ÅäÆ÷£¬ÓÃÓÚÅжÏij¸öʱ¼äµãÊÇ·ñÂú×ã¹æÔò£¬²¢ÄܼÆËãÏÂÒ»´Î/ÉÏÒ»´ÎµÄÖ´ÐÐʱ¼ä¡£ Óë±ê×¼ Cron Ïà±È£¬NewLife.Cron ¸ü¼ÓÇáÁ¿¼ò½à£¬ÊʺÏÔÚ¶¨Ê±ÈÎÎñ¡¢µ÷¶ÈϵͳÖÐʹÓᣠ**ÃüÃû¿Õ¼ä**: `NewLife.Threading` **Ô´Âë**: [NewLife.Core/Threading/Cron.cs](https://github.com/NewLifeX/X/blob/master/NewLife.Core/Threading/Cron.cs) --- ## ¿ìËÙÈëÃÅ ### ´´½¨ºÍ½âÎö ```csharp using NewLife.Threading; // ·½Ê½1£º¹¹Ôìʱ´«Èë±í´ïʽ var cron = new Cron("0 0 2 * * 1-5"); // ·½Ê½2£ºÏÈ´´½¨ºó½âÎö var cron2 = new Cron(); cron2.Parse("*/5 * * * * *"); ``` ### ÅжÏʱ¼äÊÇ·ñÆ¥Åä ```csharp var cron = new Cron("0 0 2 * * 1-5"); // ÿ¸ö¹¤×÷ÈÕÁ賿2µã // Åжϵ±Ç°Ê±¼äÊÇ·ñ·ûºÏ±í´ïʽ if (cron.IsTime(DateTime.Now)) { Console.WriteLine("ÏÖÔÚÊÇÖ´ÐÐʱ¼ä"); } // ÅжÏÌØ¶¨Ê±¼ä var time = new DateTime(2025, 1, 6, 2, 0, 0); // 2025Äê1ÔÂ6ÈÕ(ÖÜÒ») 2µã if (cron.IsTime(time)) { Console.WriteLine("¸Ãʱ¼äµã·ûºÏ¹æÔò"); } ``` ### ¼ÆËãÏÂÒ»´ÎÖ´ÐÐʱ¼ä ```csharp var cron = new Cron("0 0 2 * * *"); // ÿÌìÁ賿2µã var next = cron.GetNext(DateTime.Now); Console.WriteLine($"ÏÂÒ»´ÎÖ´ÐÐʱ¼ä£º{next}"); // ¼ÆËãÉÏÒ»´ÎÖ´ÐÐʱ¼ä var prev = cron.GetPrevious(DateTime.Now); Console.WriteLine($"ÉÏÒ»´ÎÖ´ÐÐʱ¼ä£º{prev}"); ``` --- ## ±í´ïʽÓï·¨ ### ±í´ïʽ½á¹¹ Cron ±í´ïʽÓɿոñ·Ö¸ôµÄ **6 ¸ö×Ö¶Î**×é³É£¨µÚ7¸ö×Ö¶Î"Äê"Ôݲ»Ö§³Ö£©£º ``` Ãë ·Ö Ê± ÈÕ Ô ÐÇÆÚ ``` | ×Ö¶Î | ·¶Î§ | ˵Ã÷ | |-----|------|------| | Ãë | 0-59 | ÃëÊý | | ·Ö | 0-59 | ·ÖÖÓÊý | | ʱ | 0-23 | СʱÊý£¨24Ð¡Ê±ÖÆ£© | | ÈÕ | 1-31 | ÿÔµĵڼ¸Ìì | | Ô | 1-12 | ÔÂ·Ý | | ÐÇÆÚ | 0-6 | ÐÇÆÚ¼¸£¨0=ÖÜÈÕ£¬1=ÖÜÒ»£¬...£¬6=ÖÜÁù£© | **ʾÀý**£º ``` 0 30 8 * * 1-5 // ÿ¸ö¹¤×÷ÈÕ 8:30 0 0 */2 * * * // ÿ2СʱÕûµã 0 0 0 1 * * // ÿÔÂ1ºÅÁ賿 */10 * * * * * // ÿ10Ãë ``` ### Ö§³ÖµÄÓï·¨ #### 1. ͨÅä·û `*` ±íʾËùÓпÉÄܵÄÖµ¡£ ``` * * * * * * // ÿÃë 0 * * * * * // ÿ·ÖÖÓµÄ0Ãë 0 0 * * * * // ÿСʱµÄ0·Ö0Ãë ``` #### 2. ռλ·û `?` ²»Ö¸¶¨Öµ£¬Êµ¼ÊÉϵȼÛÓÚ `*`£¬Ö÷ÒªÓÃÓÚ¼æÈÝ Quartz µÈÆäËû Cron ʵÏÖ¡£ ``` 0 0 0 ? * 1 // ÿÖÜÒ»Á賿£¨ÈÕÆÚ²»Ö¸¶¨£© ``` #### 3. ö¾Ù `a,b,c` Áгö¶à¸öÖ¸¶¨Öµ¡£ ``` 0 0 0 1,15 * * // ÿÔÂ1ºÅºÍ15ºÅÁ賿 0 0 8,12,18 * * * // ÿÌì8µã¡¢12µã¡¢18µã ``` #### 4. ·¶Î§ `a-b` ±íʾһ¸öÁ¬Ðø·¶Î§£¨±ÕÇø¼ä£©¡£ ``` 0 0 2 * * 1-5 // ÖÜÒ»µ½ÖÜÎåÁ賿2µã 0 0 9-17 * * * // ÿÌì9µãµ½17µã£¨Ã¿Ð¡Ê±£© ``` #### 5. ²½½ø `*/n`¡¢`a/n`¡¢`a-b/n` ±íʾ°´ÕÕÒ»¶¨µÄÔöÁ¿Ñ¡ÔñÖµ¡£ - `*/n`£º´Ó0¿ªÊ¼£¬Ã¿¸ônѡһ¸ö - `a/n`£º´Óa¿ªÊ¼£¬Ã¿¸ônѡһ¸ö - `a-b/n`£ºÔÚaµ½b·¶Î§ÄÚ£¬Ã¿¸ônѡһ¸ö ``` */2 * * * * * // ÿ2Ã루0,2,4,6...Ã룩 5/20 * * * * * // ÿ·ÖÖÓµÄ5Ãë¡¢25Ãë¡¢45Ãë 0 */30 * * * * // ÿ30·ÖÖÓ 0 0 0 */5 * * // ÿ5Ìì ``` #### 6. µÚ¼¸¸öÐÇÆÚ¼¸ `d#k` ºÍ `d#Lk` ½öÐÇÆÚ×Ö¶ÎÖ§³Ö£¬ÓÃÓÚ±í´ï"ÿÔµڼ¸¸öÐÇÆÚ¼¸"¡£ - `d#k`£ºÃ¿ÔµÚk¸öÐÇÆÚd - `d#Lk`£ºÃ¿Ôµ¹ÊýµÚk¸öÐÇÆÚd ``` 0 0 0 ? ? 1#1 // ÿÔµÚ1¸öÖÜÒ»Á賿 0 0 0 ? ? 5#2 // ÿÔµÚ2¸öÖÜÎåÁ賿 0 0 0 ? ? 1#L1 // ÿÔÂ×îºó1¸öÖÜÒ»Á賿 0 0 0 ? ? 3-5#L2 // ÿÔµ¹ÊýµÚ2¸öÖÜÈýµ½ÖÜÎåÁ賿 ``` **×¢Òâ**£º`#` Óï·¨»á½«ÐÇÆÚÊýÄ£ 7£¬Òò´Ë¿ÉÒÔÓà 7 ±íʾÖÜÈÕ¡£ --- ## ÐÇÆÚÆ«ÒÆ ### ĬÈÏÐÐΪ Cron ĬÈϲÉÓà Linux/.NET ·ç¸ñ£º - `0` ±íʾÖÜÈÕ (Sunday) - `1` ±íʾÖÜÒ» (Monday) - `2` ±íʾÖܶþ (Tuesday) - ... - `6` ±íʾÖÜÁù (Saturday) ### Sunday ÊôÐÔ `Sunday` ÊôÐÔÓÃÓÚµ÷Õû"ÖÜÈÕ"¶ÔÓ¦µÄÊý×ÖÆ«ÒÆ£º ```csharp var cron = new Cron(); cron.Sunday = 0; // ĬÈÏÖµ£¬0±íʾÖÜÈÕ // 0=ÖÜÈÕ£¬1=ÖÜÒ»£¬2=Öܶþ... cron.Sunday = 1; // ÐÞ¸ÄΪ1±íʾÖÜÈÕ // 1=ÖÜÈÕ£¬2=ÖÜÒ»£¬3=Öܶþ... ``` **ʹÓý¨Òé**£º - Ò»°ãÇé¿öϱ£³ÖĬÈÏ `Sunday = 0` ¼´¿É - Èç¹ûÐèÒª¼æÈÝÆäËûϵͳ£¨ÈçijЩÊý¾Ý¿â£©£¬¿Éµ÷ÕûΪ `Sunday = 1` - `Parse` ·½·¨²»»á×Ô¶¯ÍÆ¶Ï `Sunday`£¬ÐèÒªÊÖ¶¯ÉèÖà --- ## ºËÐÄ API ### IsTime - ÅжÏʱ¼äÊÇ·ñÆ¥Åä ```csharp /// <summary>Ö¸¶¨Ê±¼äÊÇ·ñλÓÚ±í´ïʽ֮ÄÚ</summary> /// <param name="time">ÒªÅжϵÄʱ¼ä</param> /// <returns>ÊÇ·ñÆ¥Åä</returns> public Boolean IsTime(DateTime time) ``` **ʾÀý**£º ```csharp var cron = new Cron("0 0 2 * * 1-5"); var time = new DateTime(2025, 1, 6, 2, 0, 0); if (cron.IsTime(time)) { Console.WriteLine("Æ¥Åä"); } ``` **×¢ÒâÊÂÏî**£º - ÅжÏʱ»á¿¼ÂÇÃë¡¢·Ö¡¢Ê±¡¢ÈÕ¡¢Ô¡¢ÐÇÆÚËùÓÐά¶È - ÐÇÆÚ×Ö¶ÎÖ§³Ö"µÚ¼¸¸öÐÇÆÚ¼¸"µÄ¸´ÔÓÅÐ¶Ï - ʱ¼ä»á°´ÕÕ `Sunday` ÊôÐÔ½øÐÐÐÇÆÚ¼ÆËã ### GetNext - »ñÈ¡ÏÂÒ»´ÎÖ´ÐÐʱ¼ä ```csharp /// <summary>»ñµÃÖ¸¶¨Ê±¼äÖ®ºóµÄÏÂÒ»´ÎÖ´ÐÐʱ¼ä£¬²»º¬Ö¸¶¨Ê±¼ä</summary> /// <param name="time">´Ó¸Ãʱ¼äÃëµÄÏÂÒ»ÃëËãÆðµÄÏÂÒ»¸öÖ´ÐÐʱ¼ä</param> /// <returns>ÏÂÒ»´ÎÖ´ÐÐʱ¼ä£¨Ãë¼¶£©£¬Èç¹ûûÓÐÆ¥ÅäÔò·µ»Ø×îСʱ¼ä</returns> public DateTime GetNext(DateTime time) ``` **ʾÀý**£º ```csharp var cron = new Cron("0 0 2 * * *"); // ÿÌìÁ賿2µã var now = DateTime.Now; var next = cron.GetNext(now); Console.WriteLine($"ÏÂÒ»´ÎÖ´ÐУº{next:yyyy-MM-dd HH:mm:ss}"); ``` **×¢ÒâÊÂÏî**£º - Èç¹û´«Èëʱ¼ä´øÓкÁÃ루Èç 09:14:23.456£©£¬»áÏòǰ¶ÔÆëµ½ÏÂÒ»Ã루09:14:24£©ºóÔÙ¼ÆËã - ·µ»ØµÄʱ¼ä²»°üº¬´«ÈëµÄʱ¼ä±¾Éí - Èç¹û1ÄêÄÚÕÒ²»µ½Æ¥Åäʱ¼ä£¬·µ»Ø `DateTime.MinValue` - **ÐÔÄܾ¯¸æ**£º¸Ã·½·¨Í¨¹ýÖðÃë±éÀú²éÕÒ£¬×î¶à±éÀú1Ä꣬²»ÊÊºÏÆµ·±µ÷Óà ### GetPrevious - »ñÈ¡ÉÏÒ»´ÎÖ´ÐÐʱ¼ä ```csharp /// <summary>»ñµÃÓëÖ¸¶¨Ê±¼ä·ûºÏ±í´ïʽµÄ×î½ü¹ýȥʱ¼ä£¨Ãë¼¶£©</summary> /// <param name="time">»ù׼ʱ¼ä</param> /// <returns>ÉÏÒ»´ÎÖ´ÐÐʱ¼ä£¬Èç¹ûûÓÐÆ¥ÅäÔò·µ»Ø×îСʱ¼ä</returns> public DateTime GetPrevious(DateTime time) ``` **ʾÀý**£º ```csharp var cron = new Cron("0 0 2 * * *"); var prev = cron.GetPrevious(DateTime.Now); Console.WriteLine($"ÉÏÒ»´ÎÖ´ÐУº{prev:yyyy-MM-dd HH:mm:ss}"); ``` ### ÅúÁ¿ Cron ¼ÆËã ```csharp /// <summary>¶ÔÒ»ÅúCron±í´ïʽ£¬»ñÈ¡ÏÂÒ»´ÎÖ´ÐÐʱ¼ä</summary> public static DateTime GetNext(String[] crons, DateTime time) /// <summary>¶ÔÒ»ÅúCron±í´ïʽ£¬»ñȡǰһ´ÎÖ´ÐÐʱ¼ä</summary> public static DateTime GetPrevious(String[] crons, DateTime time) ``` **ʾÀý**£º ```csharp var crons = new[] { "0 0 2 * * *", "0 0 14 * * *" }; // ÿÌì2µãºÍ14µã var next = Cron.GetNext(crons, DateTime.Now); Console.WriteLine($"ÏÂÒ»´ÎÖ´ÐУº{next}"); ``` --- ## ÅäºÏ TimerX ʹÓà Cron ×î³£¼ûµÄʹÓó¡¾°ÊÇÅäºÏ `TimerX` ʵÏÖ¶¨Ê±ÈÎÎñ£º ```csharp using NewLife.Threading; // ´´½¨ Cron ¶¨Ê±Æ÷£ºÃ¿¸ö¹¤×÷ÈÕÔçÉÏ8µãÖ´ÐÐ var timer = new TimerX(state => { Console.WriteLine($"Ö´ÐÐÈÎÎñ£º{DateTime.Now}"); }, null, "0 0 8 * * 1-5"); // Ö§³Ö¶à¸ö Cron ±í´ïʽ£¬·ÖºÅ·Ö¸ô var timer2 = new TimerX(state => { Console.WriteLine("Ö´ÐÐÈÎÎñ"); }, null, "0 0 2 * * 1-5;0 0 3 * * 6"); // ¹¤×÷ÈÕ2µã£¬ÖÜÁù3µã // ʹÓÃÍê±Ï¼ÇµÃÊÍ·Å timer.Dispose(); timer2.Dispose(); ``` Ïê¼û£º[TimerX ʹÓÃÊÖ²á](/NewLife/X/Blob/master/Doc/timerx-¸ß¼¶¶¨Ê±Æ÷TimerX.md) --- ## ³£Óñí´ïʽʾÀý ### ÿÃë/ÿ·Ö/ÿʱ ``` * * * * * * // ÿÃë */2 * * * * * // ÿ2Ãë */5 * * * * * // ÿ5Ãë 0 * * * * * // ÿ·ÖÖÓ 0 */5 * * * * // ÿ5·ÖÖÓ 0 */15 * * * * // ÿ15·ÖÖÓ 0 */30 * * * * // ÿ30·ÖÖÓ 0 0 * * * * // ÿСʱ 0 0 */2 * * * // ÿ2Сʱ ``` ### ÿÌì¹Ì¶¨Ê±¼ä ``` 0 0 0 * * * // ÿÌìÁ賿0µã 0 0 1 * * * // ÿÌìÁ賿1µã 0 30 8 * * * // ÿÌì8µã30·Ö 0 0 12 * * * // ÿÌìÖÐÎç12µã 0 0 23 * * * // ÿÌìÍíÉÏ23µã 0 0 0,12 * * * // ÿÌì0µãºÍ12µã 0 0 8,12,18 * * * // ÿÌì8µã¡¢12µã¡¢18µã ``` ### ¹¤×÷ÈÕ/ÖÜÄ© ``` 0 0 9 * * 1-5 // ÿ¸ö¹¤×÷ÈÕÔçÉÏ9µã 0 0 2 * * 1-5 // ÿ¸ö¹¤×÷ÈÕÁ賿2µã 0 0 10 * * 6,0 // ÿ¸öÖÜÄ©£¨ÖÜÁù¡¢ÖÜÈÕ£©10µã 0 0 0 * * 1 // ÿÖÜÒ»Á賿 0 0 0 * * 5 // ÿÖÜÎåÁ賿 ``` ### ÿÔ¹̶¨ÈÕÆÚ ``` 0 0 0 1 * * // ÿÔÂ1ºÅÁ賿 0 0 0 15 * * // ÿÔÂ15ºÅÁ賿 0 0 0 1,15 * * // ÿÔÂ1ºÅºÍ15ºÅÁ賿 0 0 0 L * * // ÿÔÂ×îºóÒ»ÌìÁ賿£¨ÐèÅäºÏÌØÊâ´¦Àí£© ``` ### ¸´ÔÓ³¡¾° ``` 0 0 2 * * 1-5 // ÿ¸ö¹¤×÷ÈÕÁ賿2µã 5/20 * * * * * // ÿ·ÖÖÓµÄ5Ãë¡¢25Ãë¡¢45Ãë 0 0 0 ? ? 1#1 // ÿÔµÚ1¸öÖÜÒ»Á賿 0 0 0 ? ? 5#L1 // ÿÔÂ×îºó1¸öÖÜÎåÁ賿 0 0 0 1-7 * 1 // ÿÔµÚÒ»¸öÖÜÒ»Á賿£¨ÁíÒ»ÖÖд·¨£© ``` --- ## ×¢ÒâÊÂÏîÓëÏÞÖÆ ### ÐÔÄÜ¿¼Á¿ `GetNext` ºÍ `GetPrevious` ·½·¨Í¨¹ý**ÖðÃë±éÀú**ʵÏÖ£¬ÐÔÄÜÌØµã£º - **Êʺϳ¡¾°**£ºµÍƵÂʵ÷Óã¬È綨ʱÈÎÎñ³õʼ»¯Ê±¼ÆËãÏÂÒ»´ÎÖ´ÐÐʱ¼ä - **²»Êʺϳ¡¾°**£º¸ßƵµ÷Óá¢ÊµÊ±Â·¾¶¡¢Èȵã´úÂë - **ÐÔÄÜÉÏÏÞ**£º×î¶à±éÀú1Ä꣨Լ3ǧÍò´ÎÑ­»·£© **½¨Òé**£º - ÔÚ `TimerX` ³õʼ»¯Ê±¼ÆËãÒ»´ÎÏÂÒ»´ÎÖ´ÐÐʱ¼ä¼´¿É - ±ÜÃâÔÚÑ­»·ÖÐÆµ·±µ÷Óà - ÈçÐè¸ßÐÔÄܳ¡¾°£¬¿¼ÂÇ×ÔÐÐʵÏÖËã·¨ ### ²»Ö§³ÖÄê·Ý×Ö¶Î µ±Ç°ÊµÏÖ½öÖ§³Ö6¸ö×ֶΣ¨Ãë¡¢·Ö¡¢Ê±¡¢ÈÕ¡¢Ô¡¢ÐÇÆÚ£©£¬**²»Ö§³ÖµÚ7¸ö×Ö¶Î"Äê"**¡£ ### ×Ö¶Îȱʡ¹æÔò - Èç¹û±í´ïʽÉÙÓÚ6¸ö×ֶΣ¬È±Ê¡×Ö¶ÎĬÈÏΪ `*` - ÀýÈ磺`0 0 2 * *` »á±»½âÎöΪ `0 0 2 * * *` ### ÐÇÆÚ×Ö¶ÎÌØÊâÐÔ - ÐÇÆÚ¼ÆËãÊÜ `Sunday` ÊôÐÔÓ°Ïì - `#` Óï·¨»á½«ÐÇÆÚÊýÄ£7£¬Òò´Ë 7 Ò²¿ÉÒÔ±íʾÖÜÈÕ - ÐÇÆÚ·¶Î§ÊÇ 0-6£¨»ò¸ù¾Ý `Sunday` µ÷ÕûΪ 1-7£© --- ## Ô´Âë½âÎö ### ½âÎöÁ÷³Ì ```csharp public Boolean Parse(String expression) { var ss = expression.Split([' '], StringSplitOptions.RemoveEmptyEntries); // ½âÎöÃë if (!TryParse(ss[0], 0, 60, out var vs)) return false; Seconds = vs; // ½âÎö·Ö if (!TryParse(ss.Length > 1 ? ss[1] : "*", 0, 60, out vs)) return false; Minutes = vs; // ... ÒÀ´Î½âÎöʱ¡¢ÈÕ¡¢Ô // ½âÎöÐÇÆÚ£¨ÌØÊâ´¦Àí£© var weeks = new Dictionary<Int32, Int32>(); if (!TryParseWeek(ss.Length > 5 ? ss[5] : "*", 0, 7, weeks)) return false; DaysOfWeek = weeks; return true; } ``` ### Æ¥ÅäÅÐ¶Ï ```csharp public Boolean IsTime(DateTime time) { // »ù´¡Ê±¼äÅÐ¶Ï if (!Seconds.Contains(time.Second) || !Minutes.Contains(time.Minute) || !Hours.Contains(time.Hour) || !DaysOfMonth.Contains(time.Day) || !Months.Contains(time.Month)) return false; // ÐÇÆÚÅжϣ¨¿¼ÂÇ Sunday Æ«ÒÆ£© var w = (Int32)time.DayOfWeek + Sunday; if (!DaysOfWeek.TryGetValue(w, out var index)) return false; // µÚ¼¸¸öÐÇÆÚ¼¸Åжϣ¨index > 0 ±íʾÕýÊýµÚ¼¸¸ö£¬< 0 ±íʾµ¹Êý£© // ... ¸´ÔÓÂß¼­ return true; } ``` --- ## ³£¼ûÎÊÌâ ### 1. ±í´ïʽ½âÎöʧ°Ü£¿ ¼ì²éÓï·¨ÊÇ·ñÕýÈ·£º - ×Ö¶ÎÊýÁ¿ÊÇ·ñΪ6¸ö£¨»ò¸üÉÙ£¬È±Ê¡Ä¬ÈÏ`*`£© - ·¶Î§ÖµÊÇ·ñÔÚÓÐЧ·¶Î§ÄÚ - ²½½øÖµÓï·¨ÊÇ·ñÕýÈ· ```csharp var cron = new Cron(); if (!cron.Parse("0 0 2 * * 1-5")) { Console.WriteLine("½âÎöʧ°Ü"); } ``` ### 2. GetNext ·µ»Ø MinValue£¿ ˵Ã÷1ÄêÄÚÕÒ²»µ½Æ¥ÅäµÄʱ¼ä£¬¿ÉÄÜÔ­Òò£º - ±í´ïʽ±¾Éíì¶Ü£¨Èç `0 0 0 31 2 *` 2ÔÂûÓÐ31ºÅ£© - ÈÕÆÚºÍÐÇÆÚ³åÍ» ### 3. ÐÇÆÚ¼ÆËã²»¶Ô£¿ ¼ì²é `Sunday` ÊôÐÔÉèÖ㺠```csharp var cron = new Cron("0 0 0 * * 1"); cron.Sunday = 0; // È·ÈÏÆ«ÒÆÁ¿ ``` ### 4. ºÁÃëÓ°Ïì¼ÆË㣿 `GetNext` »á×Ô¶¯´¦ÀíºÁÃ룬ÏòÉÏ¶ÔÆëµ½ÏÂÒ»Ã룺 ```csharp var time = new DateTime(2025, 1, 1, 9, 14, 23, 456); // ´øºÁÃë var next = cron.GetNext(time); // ´Ó 09:14:24 ¿ªÊ¼¼ÆËã ``` --- ## ²Î¿¼×ÊÁÏ - **TimerX Îĵµ**: [timerx-¸ß¼¶¶¨Ê±Æ÷TimerX.md](/NewLife/X/Blob/master/Doc/timerx-¸ß¼¶¶¨Ê±Æ÷TimerX.md) - **°¢ÀïÔÆCron²Î¿¼**: https://help.aliyun.com/document_detail/64769.html - **ÔÚÏßÎĵµ**: https://newlifex.com/core/cron - **Ô´Âë**: https://github.com/NewLifeX/X/blob/master/NewLife.Core/Threading/Cron.cs --- ## ¸üÐÂÈÕÖ¾ - **2025-01**: ÍêÉÆÎĵµ£¬²¹³äÏêϸʾÀýºÍÔ´Âë½âÎö - **2024**: Ö§³Ö .NET 9.0 - **2023**: ÓÅ»¯½âÎöÐÔÄÜ - **2022**: Ôö¼ÓÅúÁ¿Cron¼ÆËã·½·¨ - **2020**: ³õʼ°æ±¾£¬Ö§³Ö»ù±¾CronÓï·¨