1. 程式人生 > >你的程式支援複雜的時間排程嘛?如約而來的 java 版本

你的程式支援複雜的時間排程嘛?如約而來的 java 版本

你的程式支援複雜的時間排程嘛? 這篇文章介紹了時間介面卡的c#版本,是給客戶端用的,伺服器自然也要有一套對應的做法,java版本的

[年][月][日][星期][時間]

[*][*][*][*][*]

這樣利於分割,配置,清晰。

然後就是驗證,時間在不在配置的時間開發內?

當然想到的*肯定是預設支援所有的

[2015][7][*][*][10:00-11:59]

這個格式,表示2015年的7月每一天的10點到12點為配置開啟時間

[2015][7-9][*][*][10:00-11:59]

這個格式,表示2015年的7月1日到9月30的每一天的10點到12點為配置開啟時間 

[2015][7/9][*][*][10:00-11:59]

這個格式,表示2015年的7月或者9月的每一天的10點到12點為配置開啟時間

 [2015][*][*][2/4/6][10:00-11:59]
這個格式,表示2015年的每一個星期2,星期4,星期6 的每一天的10點到12點為配置開啟時間

接下來,就是驗證這個時間格式。

  1 package sz.pool;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Calendar;
  5 import java.util.Collections;
  6 
  7 /**
  8  * 時間輔助
  9  *
 10  * 
@author 失足程式設計師 11 * @Blog http://www.cnblogs.com/ty408/ 12 * @mail [email protected] 13 * @phone 13882122019 14 */ 15 public class TimeUtil { 16 17 //<editor-fold desc=" 驗證時間 返回倒計時 :[*][*][20/22][*][10:00-11:59/16:00-17:59] static public long verifyDateTime(String timeStr)"> 18 //
/ <summary> 19 /// 驗證時間:[*][*][20/22][*][10:00-11:59/16:00-17:59] 20 /// <para>第一個是年,,第二個是月,第三個是日期,第四個是星期,第五個是時間,</para> 21 /// <para>每一個引數,"-" 表示 到 如:“2015-2017”表示 2015 到 2017, "/" 表示 或者 如: “2015/2017”表示2015 或者 2017</para> 22 /// <para>返回值 -1 表示永久過期,0 表示在時間規則內,大於 0 表示倒計時</para> 23 /// </summary> 24 /** 25 * 驗證時間:[*][*][20/22][*][10:00-11:59/16:00-17:59] 26 * <\br>第一個是年,,第二個是月,第三個是日期,第四個是星期,第五個是時間, 27 * <\br>每一個引數,"-" 表示 到 如:“2015-2017”表示 2015 到 2017, "/" 表示 或者 如: 28 * “2015/2017”表示2015 或者 2017 29 * <\br>返回值 -1 表示永久過期,0 表示在時間規則內,大於 0 表示倒計時 30 * 31 * @param timeStr 32 * @return 33 */ 34 static public long verifyDateTime(String timeStr) { 35 String[] items = timeStr.split(";|;"); 36 Calendar calendar = Calendar.getInstance(); 37 for (String item : items) { 38 //驗證時間匹配 39 if (verifyConfigTimeStr(calendar, item)) { 40 return 0; 41 } 42 //未通過時間匹配,檢查返回剩餘時間 43 String[] timeStrs = item.replace("[", "").split("]"); 44 45 String times = timeStrs[4]; 46 String weeks = timeStrs[3]; 47 String days = timeStrs[2]; 48 String months = timeStrs[1]; 49 String years = timeStrs[0]; 50 51 int hour = 0, minute = 0, second = 0; 52 53 ArrayList<Integer> tempYears = getConfigDate(calendar, calendar.get(Calendar.YEAR), years); 54 ArrayList<Integer> tempMonths = getConfigDate(calendar, calendar.get(Calendar.MONTH) + 1, months); 55 ArrayList<Integer> tempDays = getConfigDate(calendar, calendar.get(Calendar.DATE), days); 56 //由於星期比較特殊所以獲取與星期相關的日期的時候有點詭異。 57 if (!"*".equals(weeks)) { 58 if (weeks.indexOf("-") > 0) { 59 //星期的間隔模式 60 String[] weeksplit = weeks.split("-"); 61 int weekmin = Integer.parseInt(weeksplit[0]); 62 int weekmax = Integer.parseInt(weeksplit[1]); 63 actionWeekDay(weekmin, weekmax, tempDays, tempMonths, tempYears); 64 } else if (weeks.indexOf("/") > 0) { 65 //星期的或模式 66 String[] weekssplit = weeks.split("/"); 67 int tempWeek; 68 for (String weekssplit1 : weekssplit) { 69 tempWeek = Integer.parseInt(weekssplit1); 70 if (0 <= tempWeek && tempWeek <= 7) { 71 actionWeekDay(tempWeek, tempWeek, tempDays, tempMonths, tempYears); 72 } 73 } 74 } else { 75 //特定星期的模式 76 int tempweek = Integer.parseInt(weeks); 77 actionWeekDay(tempweek, tempweek, tempDays, tempMonths, tempYears); 78 } 79 } else { 80 //未指定星期的模式 81 actionWeekDay(1, 7, tempDays, tempMonths, tempYears); 82 } 83 84 ArrayList<String> tempHHMMs = getConfigTimeStr(times); 85 86 //進行簡單的排序 87 Collections.sort(tempYears); 88 Collections.sort(tempMonths); 89 Collections.sort(tempDays); 90 Collections.sort(tempHHMMs); 91 92 //接下來這裡是天坑,就是構造時間器比較,然後計算出倒計時 93 for (int y = 0; y < tempYears.size(); y++) { 94 for (int m = 0; m < tempMonths.size(); m++) { 95 for (int d = 0; d < tempDays.size(); d++) { 96 if (tempYears.get(y) < calendar.get(Calendar.YEAR)) { 97 continue; 98 } 99 if (tempYears.get(y) == calendar.get(Calendar.YEAR) && tempMonths.get(m) - 1 < calendar.get(Calendar.MONTH)) { 100 continue; 101 } 102 if (tempYears.get(y) == calendar.get(Calendar.YEAR) && tempMonths.get(m) - 1 == calendar.get(Calendar.MONTH) && tempDays.get(d) < calendar.get(Calendar.DATE)) { 103 continue; 104 } 105 for (int h = 0; h < tempHHMMs.size(); h++) { 106 String[] hhmm = tempHHMMs.get(h).split(":|:"); 107 hour = Integer.parseInt(hhmm[0]); 108 minute = Integer.parseInt(hhmm[1]); 109 Calendar calendar1 = Calendar.getInstance(); 110 calendar1.set(tempYears.get(y), (tempMonths.get(m) - 1), tempDays.get(d), hour, minute, second); 111 // System.out.println(DF2.format(calendar1.getTime()) + " " + DF2.format(calendar.getTime())); 112 // System.out.println(calendar1.getTimeInMillis() + " " + calendar.getTimeInMillis()); 113 if (calendar1.getTimeInMillis() > calendar.getTimeInMillis()) { 114 if (verifyConfigTimeStr(calendar1, item)) { 115 return calendar1.getTimeInMillis() - calendar.getTimeInMillis(); 116 } 117 } 118 } 119 } 120 } 121 } 122 } 123 return -1; 124 } 125 //</editor-fold> 126 127 //<editor-fold desc=" 處理星期包含的日期 日 static void actionWeekDay(int weekmin, int weekmax, ArrayList<Integer> days, ArrayList<Integer> months, ArrayList<Integer> years)"> 128 /** 129 * 處理星期包含的日期 日 130 * 131 * @param weekmin 132 * @param weekmax 133 * @param days 134 * @param months 135 * @param years 136 */ 137 static void actionWeekDay(int weekmin, int weekmax, ArrayList<Integer> days, ArrayList<Integer> months, ArrayList<Integer> years) { 138 Calendar nowWeekDate = Calendar.getInstance(); 139 Integer[] tempMonths, tempYears; 140 tempYears = years.toArray(new Integer[0]); 141 tempMonths = months.toArray(new Integer[0]); 142 for (int itemYear : tempYears) { 143 for (int itemMonth : tempMonths) { 144 int itemDay = 1; 145 if (nowWeekDate.get(Calendar.MONTH) + 1 == itemMonth) { 146 itemDay = nowWeekDate.get(Calendar.DATE); 147 } 148 Calendar date = Calendar.getInstance(); 149 date.set(itemYear, itemMonth - 1, itemDay); 150 for (int i = 0; i < 7; i++) { 151 int week = date.get(Calendar.DAY_OF_WEEK) - 1; 152 if (week < 1) { 153 week = 7; 154 } 155 if (weekmin <= week && week <= weekmax) { 156 if (!days.contains(date.get(Calendar.DATE))) { 157 days.add(date.get(Calendar.DATE)); 158 } 159 if (!months.contains(date.get(Calendar.MONTH) + 1)) { 160 months.add(date.get(Calendar.MONTH) + 1); 161 } 162 if (!years.contains(date.get(Calendar.YEAR))) { 163 years.add(date.get(Calendar.YEAR)); 164 } 165 } 166 date.add(Calendar.DATE, 1); 167 } 168 } 169 } 170 } 171 //</editor-fold> 172 173 //<editor-fold desc="驗證時間:[*][*][20/22][*][10:00-11:59/16:00-17:59] static public boolean verifyConfigTimeStr(String timeStr)"> 174 /** 175 * 驗證時間:[*][*][20/22][*][10:00-11:59/16:00-17:59] 176 * <para>第一個是年,,第二個是月,第三個是日期,第四個是星期,第五個是時間,</para> 177 * <para>每一個引數,"-" 表示 到 如:“2015-2017”表示 2015 到 2017, "/" 表示 或者 如: 178 * “2015/2017”表示2015 或者 2017</para> 179 * 180 */ 181 static public boolean verifyConfigTimeStr(String timeStr) { 182 return verifyConfigTimeStr(Calendar.getInstance(), timeStr); 183 } 184 //</editor-fold> 185 186 //<editor-fold desc="驗證時間:[*][*][20/22][*][10:00-11:59/16:00-17:59] static boolean verifyConfigTimeStr(Calendar date, String timeStr)"> 187 /** 188 * 驗證時間:[*][*][20/22][*][10:00-11:59/16:00-17:59] 189 * <para>第一個是年,,第二個是月,第三個是日期,第四個是星期,第五個是時間,</para> 190 * <para>每一個引數,"-" 表示 到 如:“2015-2017”表示 2015 到 2017, "/" 表示 或者 如: 191 * “2015/2017”表示2015 或者 2017</para> 192 * 193 */ 194 static boolean verifyConfigTimeStr(Calendar date, String timeStr) { 195 String[] timeStrs = timeStr.replace("[", "").split("]"); 196 if (verifyDate(date.get(Calendar.YEAR), timeStrs[0])) { 197 if (verifyDate(date.get(Calendar.MONTH) + 1, timeStrs[1])) { 198 // {"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"}; 199 int week = date.get(Calendar.DAY_OF_WEEK) - 1; 200 if (week < 1) { 201 week = 7; 202 }//星期天 203 if (verifyDate(week, timeStrs[3])) { 204 if (verifyDate(date.get(Calendar.DATE), timeStrs[2])) { 205 if (verifyTime(date, timeStrs[4])) { 206 return true; 207 } 208 } 209 } 210 } 211 } 212 return false; 213 } 214 //</editor-fold> 215 216 //<editor-fold desc=" 驗證當前時間 年,月,日,星期,是否符合 static boolean verifyDate(int nowItem, String items)"> 217 /** 218 * 驗證當前時間 年,月,日,星期,是否符合 219 * 220 * @param nowItem 引數 221 * @param items 1-7;表示 1 到 7 , 1/7 表示 1 或者 7 222 * @return 223 */ 224 static boolean verifyDate(int nowItem, String items) { 225 String nowItemStr = String.valueOf(nowItem); 226 if ("*".equals(items) || nowItemStr.equals(items)) { 227 return true; 228 } else if (items.indexOf("-") > 0) {//區間劃分 229 String[] itemsplit = items.split("-"); 230 int item1 = Integer.parseInt(itemsplit[0]); 231 int item2 = Integer.parseInt(itemsplit[1]); 232 if (item1 <= nowItem && nowItem <= item2) { 233 return true; 234 } 235 } else if (items.indexOf("/") > 0) {//或劃分 236 String[] weekssplit = items.split("/"); 237 for (String item : weekssplit) { 238 if (nowItemStr.equals(item)) { 239 return true; 240 } 241 } 242 } 243 return false; 244 } 245 //</editor-fold> 246 247 //<editor-fold desc="驗證當期時間格式 static boolean verifyTime(Calendar date, String itemTime)"> 248 /** 249 * 驗證當期時間格式 250 * 251 * @param date 252 * @param itemTime 253 * @return 254 */ 255 static boolean verifyTime(Calendar date, String itemTime) { 256 boolean ret = false; 257 if (!"*".equals(itemTime)) { 258 String[] items = itemTime.split("/"); 259 for (String item : items) { 260 String[] itemTimes = item.split("-"); 261 String[] hhmm = itemTimes[0].split(":|:"); 262 int hh = Integer.parseInt(hhmm[0]); 263 int mm = Integer.parseInt(hhmm[1]); 264 if (date.get(Calendar.HOUR_OF_DAY) > hh || (date.get(Calendar.HOUR_OF_DAY) == hh && date.get(Calendar.MINUTE) >= mm)) { 265 if (itemTimes.length > 1) { 266 String[] hhmm1 = itemTimes[1].split(":|:"); 267 int hh1 = Integer.parseInt(hhmm1[0]); 268 int mm1 = Integer.parseInt(hhmm1[1]); 269 if (date.get(Calendar.HOUR_OF_DAY) < hh1 || (date.get(Calendar.HOUR_OF_DAY) == hh1 && date.get(Calendar.MINUTE) < mm1)) { 270 ret = true; 271 } else { 272 ret = false; 273 } 274 } else { 275 ret = true; 276 } 277 } else { 278 ret = false; 279 } 280 if (ret) { 281 break; 282 } 283 } 284 } else { 285 ret = true; 286 } 287 return ret; 288 } 289 //</editor-fold> 290 291 //<editor-fold desc="獲取配置的年月日星期等資訊 static ArrayList<Integer> getConfigDate(Calendar calendar, int p1, String p3)"> 292 static ArrayList<Integer> getConfigDate(Calendar calendar, int p1, String p3) { 293 ArrayList<Integer> rets = new ArrayList<Integer>(); 294 String p1Str = String.valueOf(p1); 295 if ("*".equals(p3) || p1Str.equals(p3)) { 296 rets.add(p1); 297 rets.add(p1 + 1); 298 } else if (p3.indexOf("-") > 0) { 299 String[] weeksplit = p3.split("-"); 300 int k1 = Integer.parseInt(weeksplit[0]); 301 int k2 = Integer.parseInt(weeksplit[0]); 302 for (int i = k1; i <= k2 + 1; i++) { 303 rets.add(i); 304 } 305 } else if (p3.indexOf("/") > 0) { 306 String[] weekssplit = p3.split("/"); 307 for (String item : weekssplit) { 308 int temp = Integer.parseInt(item); 309 rets.add(temp); 310 } 311 } else { 312 rets.add(Integer.parseInt(p3)); 313 } 314 return rets; 315 } 316 //</editor-fold> 317 318 //<editor-fold desc="獲取配置的時間字串 static ArrayList<String> getConfigTimeStr(String itemTime)"> 319 /** 320 * 必須類似的格式 單條 00:00-23:59 多條00:00-23:59/00:00-23:59 321 * 322 * @param itemTime 323 * @return 324 */ 325 static ArrayList<String> getConfigTimeStr(String itemTime) { 326 ArrayList<String> retObjs = new ArrayList<String>(); 327 // 00:00-23:59 328 if (!"*".equals(itemTime)) { 329 String[] items = itemTime.split("/"); 330 for (String item : items) { 331 String[] itemTimes = item.split("-"); 332 retObjs.add(itemTimes[0]); 333 } 334 } else { 335 retObjs.add("00:00"); 336 } 337 return retObjs; 338 } 339 //</editor-fold> 340 }

以上程式碼,有兩個public的方法,一個是返回值bool變數,表示是否在配置開發時間內,另外一個是返回值long型,-1表示永久過期,0表示開發時間,大於0表示倒計時;

那麼問題來了,伺服器是java開發的,客戶端是u3d c#開發的,客戶端和伺服器的語言不一樣,使用的date也就不一樣,

C#使用的是0001年1月1日,0晨開始的,java是用的是1970年1月1日0晨時間,並且是標準的gmt +8 時區,

蛋疼的研究了一上午。c#無論使用utc時間還是local時間,都和java相差8小時,尿了。。。。

伺服器會在間隔一段時間同步一次伺服器當前時間給客戶端,然後客戶端就可以得到dateTime了

 1         static DateTime dt1970 = new DateTime(1970, 1, 1, 0, 0, 0);
 2 
 3         /// <summary>
 4         /// 將java毫秒數轉化成當前時間
 5         /// </summary>
 6         public static DateTime DateNow(long milliseconds)
 7         {
 8             // .net開發中計算的都是標準時區的差,但java的解析時間跟時區有關,
 9             // 而我們的java伺服器系統時區不是標準時區,解析時間會差8個小時。
10             TimeSpan span = TimeSpan.FromMilliseconds(milliseconds) + TimeSpan.FromHours(8);
11             return dt1970 + span;
12         }

c#下面得到一個long型時間與java保持一致

 1         /// <summary>
 2         /// 將特定時間轉化成java一直的毫秒數
 3         /// </summary>
 4         public static long CurrentTimeMillis(DateTime dt)
 5         {
 6             TimeSpan span = dt - dt1970;
 7             // .net開發中計算的都是標準時區的差,但java的解析時間跟時區有關,
 8             // 而我們的java伺服器系統時區不是標準時區,解析時間會差8個小時。
 9             span -= TimeSpan.FromHours(8);
10             return (long)span.TotalMilliseconds;
11         }

好了,,時間驗證器,和時間同步問題,java和c#兩個版本