00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 module mango.time.Rfc1123;
00041
00042 private import mango.sys.Epoch;
00043
00044 private import mango.format.Format;
00045
00046 extern (C) int memcmp (char *, char *, uint);
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 class Rfc1123 : Epoch
00063 {
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 final static char[] format (long time)
00074 {
00075 return format (new char[40], time);
00076 }
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 final static char[] format (char[] buffer, long time)
00091 {
00092
00093 if (time == InvalidEpoch)
00094 return "";
00095
00096
00097 Fields fields;
00098 fields.setUtcTime (time);
00099
00100
00101 Format.Sprintf s;
00102 s (buffer);
00103
00104
00105 int len = s.format ("%.3s, %02d %.3s %04d %02d:%02d:%02d GMT",
00106 fields.toDowName,
00107 fields.day,
00108 fields.toMonthName,
00109 fields.year,
00110 fields.hour,
00111 fields.min,
00112 fields.sec
00113 );
00114
00115
00116 return buffer [0..len];
00117 }
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 static long parse (char[] date, uint* ate = null)
00130 {
00131 int len;
00132 ulong value;
00133
00134 if ((len = rfc1123 (date, value)) > 0 ||
00135 (len = rfc850 (date, value)) > 0 ||
00136 (len = asctime (date, value)) > 0)
00137 {
00138 if (ate)
00139 *ate = len;
00140 return value;
00141 }
00142 return InvalidEpoch;
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 private static int rfc1123 (char[] src, inout ulong value)
00155 {
00156 Fields fields;
00157 char* p = src.ptr;
00158
00159 bool date (inout char* p)
00160 {
00161 return ((fields.day = parseInt(p)) > 0 &&
00162 *p++ == ' ' &&
00163 (fields.month = parseMonth(p)) > 0 &&
00164 *p++ == ' ' &&
00165 (fields.year = parseInt(p)) > 0);
00166 }
00167
00168 if (parseShortDay(p) >= 0 &&
00169 *p++ == ',' &&
00170 *p++ == ' ' &&
00171 date (p) &&
00172 *p++ == ' ' &&
00173 time (fields, p) &&
00174 *p++ == ' ' &&
00175 p[0..3] == "GMT")
00176 {
00177 value = fields.getUtcTime;
00178 return (p+3) - src.ptr;
00179 }
00180
00181 return 0;
00182 }
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 private static int rfc850 (char[] src, inout ulong value)
00193 {
00194 Fields fields;
00195 char* p = src.ptr;
00196
00197 bool date (inout char* p)
00198 {
00199 return ((fields.day = parseInt(p)) > 0 &&
00200 *p++ == '-' &&
00201 (fields.month = parseMonth(p)) > 0 &&
00202 *p++ == '-' &&
00203 (fields.year = parseInt(p)) > 0);
00204 }
00205
00206 if (parseFullDay(p) >= 0 &&
00207 *p++ == ',' &&
00208 *p++ == ' ' &&
00209 date (p) &&
00210 *p++ == ' ' &&
00211 time (fields, p) &&
00212 *p++ == ' ' &&
00213 p[0..3] == "GMT")
00214 {
00215 if (fields.year <= 70)
00216 fields.year += 2000;
00217 else
00218 if (fields.year <= 99)
00219 fields.year += 1900;
00220
00221 value = fields.getUtcTime;
00222 return (p+3) - src.ptr;
00223 }
00224
00225 return 0;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 private static int asctime (char[] src, inout ulong value)
00237 {
00238 Fields fields;
00239 char* p = src.ptr;
00240
00241 bool date (inout char* p)
00242 {
00243 return ((fields.month = parseMonth(p)) > 0 &&
00244 *p++ == ' ' &&
00245 ((fields.day = parseInt(p)) > 0 ||
00246 (*p++ == ' ' &&
00247 (fields.day = parseInt(p)) > 0)));
00248 }
00249
00250 if (parseShortDay(p) >= 0 &&
00251 *p++ == ' ' &&
00252 date (p) &&
00253 *p++ == ' ' &&
00254 time (fields, p) &&
00255 *p++ == ' ' &&
00256 (fields.year = parseInt (p)) > 0)
00257 {
00258 value = fields.getUtcTime;
00259 return p - src.ptr;
00260 }
00261
00262 return 0;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271 private static bool time (inout Fields fields, inout char* p)
00272 {
00273 return ((fields.hour = parseInt(p)) > 0 &&
00274 *p++ == ':' &&
00275 (fields.min = parseInt(p)) > 0 &&
00276 *p++ == ':' &&
00277 (fields.sec = parseInt(p)) > 0);
00278 }
00279
00280
00281
00282
00283
00284
00285
00286 private static int parseMonth (inout char* p)
00287 {
00288 int month;
00289
00290 switch (p[0..3])
00291 {
00292 case "Jan":
00293 month = 1;
00294 break;
00295 case "Feb":
00296 month = 2;
00297 break;
00298 case "Mar":
00299 month = 3;
00300 break;
00301 case "Apr":
00302 month = 4;
00303 break;
00304 case "May":
00305 month = 5;
00306 break;
00307 case "Jun":
00308 month = 6;
00309 break;
00310 case "Jul":
00311 month = 7;
00312 break;
00313 case "Aug":
00314 month = 8;
00315 break;
00316 case "Sep":
00317 month = 9;
00318 break;
00319 case "Oct":
00320 month = 10;
00321 break;
00322 case "Nov":
00323 month = 11;
00324 break;
00325 case "Dec":
00326 month = 12;
00327 break;
00328 default:
00329 return month;
00330 }
00331
00332 p += 3;
00333 return month;
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 private static int parseShortDay (inout char* p)
00343 {
00344 int day;
00345
00346 switch (p[0..3])
00347 {
00348 case "Sun":
00349 day = 0;
00350 break;
00351 case "Mon":
00352 day = 1;
00353 break;
00354 case "Tue":
00355 day = 2;
00356 break;
00357 case "Wed":
00358 day = 3;
00359 break;
00360 case "Thu":
00361 day = 4;
00362 break;
00363 case "Fri":
00364 day = 5;
00365 break;
00366 case "Sat":
00367 day = 6;
00368 break;
00369 default:
00370 return -1;
00371 }
00372
00373 p += 3;
00374 return day;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383 private static int parseFullDay (inout char* p)
00384 {
00385 foreach (int i, char[] day; Fields.Days)
00386 if (memcmp (day, p, day.length) == 0)
00387 {
00388 p += day.length;
00389 return i;
00390 }
00391 return -1;
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401 private static int parseInt (inout char* p)
00402 {
00403 int value;
00404
00405 while (*p >= '0' && *p <= '9')
00406 value = value * 10 + *p++ - '0';
00407 return value;
00408 }
00409 }