wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #define DEBUG |
2 | /* |
||
3 | * ClockCmd.java -- |
||
4 | * |
||
5 | * Implements the built-in "clock" Tcl command. |
||
6 | * |
||
7 | * Copyright (c) 1998-2000 Christian Krone. |
||
8 | * Copyright (c) 1997 Cornell University. |
||
9 | * Copyright (c) 1995-1997 Sun Microsystems, Inc. |
||
10 | * Copyright (c) 1992-1995 Karl Lehenbauer and Mark Diekhans. |
||
11 | * |
||
12 | * See the file "license.terms" for information on usage and |
||
13 | * redistribution of this file, and for a DISCLAIMER OF ALL |
||
14 | * WARRANTIES. |
||
15 | * |
||
16 | * Included in SQLite3 port to C# for use in testharness only; 2008 Noah B Hart |
||
17 | * |
||
18 | * RCS @(#) $Id: ClockCmd.java,v 1.6 2003/02/03 04:48:46 mdejong Exp $ |
||
19 | * |
||
20 | */ |
||
21 | using System; |
||
22 | using System.Globalization; |
||
23 | using System.Text; |
||
24 | using System.Collections; |
||
25 | |||
26 | |||
27 | namespace tcl.lang |
||
28 | { |
||
29 | |||
30 | /// <summary> This class implements the built-in "clock" command in Tcl.</summary> |
||
31 | |||
32 | class ClockCmd : Command |
||
33 | { |
||
34 | |||
35 | private static readonly string[] validCmds = new string[] { "clicks", "format", "scan", "seconds" }; |
||
36 | |||
37 | private const int CMD_CLICKS = 0; |
||
38 | private const int CMD_FORMAT = 1; |
||
39 | private const int CMD_SCAN = 2; |
||
40 | private const int CMD_SECONDS = 3; |
||
41 | |||
42 | private static readonly string[] clicksOpts = new string[] { "-milliseconds" }; |
||
43 | |||
44 | private const int OPT_CLICKS_MILLISECONDS = 0; |
||
45 | |||
46 | private static readonly string[] formatOpts = new string[] { "-format", "-gmt" }; |
||
47 | |||
48 | private const int OPT_FORMAT_FORMAT = 0; |
||
49 | private const int OPT_FORMAT_GMT = 1; |
||
50 | |||
51 | private static readonly string[] scanOpts = new string[] { "-base", "-gmt" }; |
||
52 | |||
53 | private const int OPT_SCAN_BASE = 0; |
||
54 | private const int OPT_SCAN_GMT = 1; |
||
55 | |||
56 | internal const int EPOCH_YEAR = 1970; |
||
57 | internal const int MILLIS_PER_HOUR = 60 * 60 * 1000; |
||
58 | public TCL.CompletionCode cmdProc( Interp interp, TclObject[] objv ) |
||
59 | { |
||
60 | int clockVal; // Time value as seconds of epoch. |
||
61 | string dateString; // Time value as string. |
||
62 | int argIx; // Counter over arguments. |
||
63 | string format = null; // User specified format string. |
||
64 | bool useGmt = false; // User specified flag to use gmt. |
||
65 | TclObject baseObj = null; // User specified raw value of baseClock. |
||
66 | System.DateTime baseClock; // User specified time value. |
||
67 | System.DateTime date; // Parsed date value. |
||
68 | |||
69 | if ( objv.Length < 2 ) |
||
70 | { |
||
71 | throw new TclNumArgsException( interp, 1, objv, "option ?arg ...?" ); |
||
72 | } |
||
73 | int cmd = TclIndex.get( interp, objv[1], validCmds, "option", 0 ); |
||
74 | |||
75 | switch ( cmd ) |
||
76 | { |
||
77 | |||
78 | case CMD_CLICKS: |
||
79 | { |
||
80 | if ( objv.Length > 3 ) |
||
81 | { |
||
82 | throw new TclNumArgsException( interp, 2, objv, "?-milliseconds?" ); |
||
83 | } |
||
84 | if ( objv.Length == 3 ) |
||
85 | { |
||
86 | // We can safely ignore the -milliseconds options, since |
||
87 | // we measure the clicks in milliseconds anyway... |
||
88 | int clicksOpt = TclIndex.get( interp, objv[2], clicksOpts, "switch", 0 ); |
||
89 | } |
||
90 | long millis = ( System.DateTime.Now.Ticks - 621355968000000000 ) / 10000; |
||
91 | int clicks = (int)( millis % System.Int32.MaxValue ); |
||
92 | interp.setResult( clicks ); |
||
93 | break; |
||
94 | } |
||
95 | |||
96 | |||
97 | case CMD_FORMAT: |
||
98 | { |
||
99 | if ( ( objv.Length < 3 ) || ( objv.Length > 7 ) ) |
||
100 | { |
||
101 | throw new TclNumArgsException( interp, 2, objv, "clockval ?-format string? ?-gmt boolean?" ); |
||
102 | } |
||
103 | clockVal = TclInteger.get( interp, objv[2] ); |
||
104 | |||
105 | for ( argIx = 3; argIx + 1 < objv.Length; argIx += 2 ) |
||
106 | { |
||
107 | int formatOpt = TclIndex.get( interp, objv[argIx], formatOpts, "switch", 0 ); |
||
108 | switch ( formatOpt ) |
||
109 | { |
||
110 | |||
111 | case OPT_FORMAT_FORMAT: |
||
112 | { |
||
113 | |||
114 | format = objv[argIx + 1].ToString(); |
||
115 | break; |
||
116 | } |
||
117 | |||
118 | case OPT_FORMAT_GMT: |
||
119 | { |
||
120 | useGmt = TclBoolean.get( interp, objv[argIx + 1] ); |
||
121 | break; |
||
122 | } |
||
123 | } |
||
124 | } |
||
125 | if ( argIx < objv.Length ) |
||
126 | { |
||
127 | throw new TclNumArgsException( interp, 2, objv, "clockval ?-format string? ?-gmt boolean?" ); |
||
128 | } |
||
129 | FormatClock( interp, clockVal, useGmt, format ); |
||
130 | break; |
||
131 | } |
||
132 | |||
133 | |||
134 | case CMD_SCAN: |
||
135 | { |
||
136 | if ( ( objv.Length < 3 ) || ( objv.Length > 7 ) ) |
||
137 | { |
||
138 | throw new TclNumArgsException( interp, 2, objv, "dateString ?-base clockValue? ?-gmt boolean?" ); |
||
139 | } |
||
140 | |||
141 | dateString = objv[2].ToString(); |
||
142 | |||
143 | for ( argIx = 3; argIx + 1 < objv.Length; argIx += 2 ) |
||
144 | { |
||
145 | int scanOpt = TclIndex.get( interp, objv[argIx], scanOpts, "switch", 0 ); |
||
146 | switch ( scanOpt ) |
||
147 | { |
||
148 | |||
149 | case OPT_SCAN_BASE: |
||
150 | { |
||
151 | baseObj = objv[argIx + 1]; |
||
152 | break; |
||
153 | } |
||
154 | |||
155 | case OPT_SCAN_GMT: |
||
156 | { |
||
157 | useGmt = TclBoolean.get( interp, objv[argIx + 1] ); |
||
158 | break; |
||
159 | } |
||
160 | } |
||
161 | } |
||
162 | if ( argIx < objv.Length ) |
||
163 | { |
||
164 | throw new TclNumArgsException( interp, 2, objv, "clockval ?-format string? ?-gmt boolean?" ); |
||
165 | } |
||
166 | if ( baseObj != null ) |
||
167 | { |
||
168 | long seconds = TclInteger.get( interp, baseObj ); |
||
169 | baseClock = new System.DateTime( (long)seconds * 10000 * 1000 + 621355968000000000 ); |
||
170 | } |
||
171 | else |
||
172 | { |
||
173 | baseClock = System.DateTime.Now; |
||
174 | } |
||
175 | try |
||
176 | { |
||
177 | date = GetDate( dateString, baseClock, useGmt ); |
||
178 | } |
||
179 | catch ( FormatException ) |
||
180 | { |
||
181 | throw new TclException( interp, "unable to convert date-time string \"" + dateString + "\"" ); |
||
182 | } |
||
183 | long millis = ( date.Ticks - 621355968000000000 ) / 10000; |
||
184 | int seconds2 = (int)( millis / 1000 ); |
||
185 | interp.setResult( seconds2 ); |
||
186 | break; |
||
187 | } |
||
188 | |||
189 | |||
190 | case CMD_SECONDS: |
||
191 | { |
||
192 | if ( objv.Length != 2 ) |
||
193 | { |
||
194 | throw new TclNumArgsException( interp, 2, objv, null ); |
||
195 | } |
||
196 | long millis = ( System.DateTime.Now.Ticks - 621355968000000000 ) / 10000; |
||
197 | int seconds = (int)( millis / 1000 ); |
||
198 | interp.setResult( seconds ); |
||
199 | break; |
||
200 | } |
||
201 | } |
||
202 | return TCL.CompletionCode.RETURN; |
||
203 | } |
||
204 | private void FormatClock( Interp interp, int clockVal, bool useGMT, string format ) |
||
205 | { |
||
206 | DateTime date = new DateTime( (long)clockVal * 10000 * 1000 + 621355968000000000 ); |
||
207 | |||
208 | DateTimeFormatInfo formatInfo = new DateTimeFormatInfo(); |
||
209 | string fmt, locFmt; |
||
210 | |||
211 | GregorianCalendar calendar = new GregorianCalendar(); |
||
212 | |||
213 | System.Int32[] temp_int_array; |
||
214 | temp_int_array = new System.Int32[3]; |
||
215 | temp_int_array[0] = 0; |
||
216 | temp_int_array[1] = 0; |
||
217 | temp_int_array[2] = 0; |
||
218 | System.Int32[] fp = temp_int_array; |
||
219 | StringBuilder result = new StringBuilder(); |
||
220 | |||
221 | if ( (System.Object)format == null ) |
||
222 | { |
||
223 | format = new StringBuilder( "%a %b %d %H:%M:%S %Z %Y" ).ToString(); |
||
224 | } |
||
225 | |||
226 | if ( useGMT ) |
||
227 | { |
||
228 | date = date.ToUniversalTime(); |
||
229 | } |
||
230 | if ( format.Equals( "%Q" ) ) |
||
231 | { |
||
232 | // Enterprise Stardate. (seems to be Star Track fan coding) |
||
233 | // ATK not tested |
||
234 | int trekYear = date.Year + 377 - 2323; |
||
235 | int trekDay = ( date.DayOfYear * 1000 ) / ( calendar.IsLeapYear( date.Year ) ? 366 : 365 ); |
||
236 | int trekHour = ( 24 * 60 + date.Minute ) / 144; |
||
237 | |||
238 | interp.setResult( "Stardate " + ( trekYear < 10 ? "0" : "" ) + ( trekYear * 1000 + trekDay ) + '.' + trekHour ); |
||
239 | return; |
||
240 | } |
||
241 | |||
242 | for ( int ix = 0; ix < format.Length; ix++ ) |
||
243 | { |
||
244 | if ( format[ix] == '%' && ix + 1 < format.Length ) |
||
245 | { |
||
246 | switch ( format[++ix] ) |
||
247 | { |
||
248 | |||
249 | case '%': |
||
250 | result.Append( '%' ); |
||
251 | break; |
||
252 | |||
253 | case 'a': |
||
254 | result.Append( date.ToString( "ddd", formatInfo ) ); |
||
255 | break; |
||
256 | |||
257 | case 'A': |
||
258 | result.Append( date.ToString( "dddd", formatInfo ) ); |
||
259 | break; |
||
260 | case 'b': |
||
261 | case 'h': |
||
262 | result.Append( date.ToString( "MMM", formatInfo ) ); |
||
263 | break; |
||
264 | case 'B': |
||
265 | result.Append( date.ToString( "MMMM", formatInfo ) ); |
||
266 | break; |
||
267 | case 'c': |
||
268 | result.Append( date.ToString() ); |
||
269 | break; |
||
270 | case 'C': |
||
271 | int century = date.Year / 100; |
||
272 | result.Append( ( century < 10 ? "0" : "" ) + century ); |
||
273 | break; |
||
274 | case 'd': |
||
275 | result.Append( date.ToString( "dd", formatInfo ) ); |
||
276 | break; |
||
277 | case 'D': |
||
278 | result.Append( date.ToString( "MM/dd/yy", formatInfo ) ); |
||
279 | break; |
||
280 | case 'e': |
||
281 | result.Append( date.ToString( "%d", formatInfo ) ); |
||
282 | break; |
||
283 | case 'H': |
||
284 | result.Append( date.ToString( "HH", formatInfo ) ); |
||
285 | break; |
||
286 | case 'I': |
||
287 | result.Append( date.ToString( "hh", formatInfo ) ); |
||
288 | break; |
||
289 | case 'j': |
||
290 | result.Append( date.Year.ToString( "0###" ) ); |
||
291 | break; |
||
292 | case 'k': |
||
293 | result.Append( date.ToString( "H", formatInfo ) ); |
||
294 | break; |
||
295 | case 'l': |
||
296 | result.Append( date.ToString( "%h", formatInfo ) ); |
||
297 | break; |
||
298 | case 'm': |
||
299 | // Month number (01 - 12). |
||
300 | result.Append( date.ToString( "MM", formatInfo ) ); |
||
301 | break; |
||
302 | case 'M': |
||
303 | // Minute (00 - 59). |
||
304 | result.Append( date.ToString( "mm", formatInfo ) ); |
||
305 | break; |
||
306 | case 'n': |
||
307 | // Insert a newline. |
||
308 | result.Append( '\n' ); |
||
309 | break; |
||
310 | case 'p': |
||
311 | // AM/PM indicator. |
||
312 | result.Append( date.ToString( "tt", formatInfo ) ); |
||
313 | break; |
||
314 | case 'r': |
||
315 | // %r |
||
316 | //Time in a locale-specific "meridian" format. The "meridian" format in the default "C" locale is "%I:%M:%S %p". |
||
317 | result.Append( date.ToString( "hh:mm:ss tt", formatInfo ) ); |
||
318 | break; |
||
319 | case 'R': |
||
320 | //%R |
||
321 | //Time as %H:%M. |
||
322 | result.Append( date.ToString( "HH:MM", formatInfo ) ); |
||
323 | break; |
||
324 | case 's': |
||
325 | //%s |
||
326 | //Count of seconds since the epoch, expressed as a decimal integer. |
||
327 | result.Append( ( date.Ticks / 1000 ).ToString() ); |
||
328 | break; |
||
329 | |||
330 | case 'S': |
||
331 | //%S |
||
332 | //Seconds (00 - 59). |
||
333 | result.Append( date.ToString( "ss", formatInfo ) ); |
||
334 | break; |
||
335 | case 't': |
||
336 | //%t |
||
337 | //Insert a tab. |
||
338 | result.Append( '\t' ); |
||
339 | break; |
||
340 | |||
341 | case 'T': |
||
342 | //%T |
||
343 | //Time as %H:%M:%S. |
||
344 | result.Append( date.ToString( "HH:mm:ss", formatInfo ) ); |
||
345 | break; |
||
346 | |||
347 | case 'u': |
||
348 | //%u |
||
349 | //Weekday number (Monday = 1, Sunday = 7). |
||
350 | if ( date.DayOfWeek == DayOfWeek.Sunday ) |
||
351 | { |
||
352 | result.Append( "7" ); |
||
353 | } |
||
354 | else |
||
355 | { |
||
356 | result.Append( ( (int)date.DayOfWeek ).ToString() ); |
||
357 | } |
||
358 | break; |
||
359 | case 'U': |
||
360 | //%U |
||
361 | //Week of year (00 - 52), Sunday is the first day of the week. |
||
362 | int weekS = GetWeek( date, System.DayOfWeek.Sunday, false ); |
||
363 | result.Append( ( weekS < 10 ? "0" : "" ) + weekS ); |
||
364 | break; |
||
365 | |||
366 | case 'V': |
||
367 | //%V |
||
368 | //Week of year according to ISO-8601 rules. Week 1 of a given year is the week containing 4 January. |
||
369 | int isoWeek = GetWeek( date, System.DayOfWeek.Monday, true ); |
||
370 | result.Append( ( isoWeek < 10 ? "0" : "" ) + isoWeek ); |
||
371 | break; |
||
372 | |||
373 | case 'w': |
||
374 | //%w |
||
375 | //Weekday number (Sunday = 0, Saturday = 6). |
||
376 | result.Append( ( (int)date.DayOfWeek ).ToString() ); |
||
377 | break; |
||
378 | |||
379 | case 'W': |
||
380 | //%W |
||
381 | //Week of year (00 - 52), Monday is the first day of the week. |
||
382 | int weekM = GetWeek( date, System.DayOfWeek.Monday, false ); |
||
383 | result.Append( ( weekM < 10 ? "0" : "" ) + weekM ); |
||
384 | break; |
||
385 | case 'x': |
||
386 | //%x |
||
387 | //Locale specific date format. The format for a date in the default "C" locale for Unix/Mac is "%m/%d/%y". On Windows, this value is the locale specific short date format, as specified in the Regional Options control panel settings. |
||
388 | result.Append( date.ToShortDateString() ); |
||
389 | break; |
||
390 | |||
391 | case 'X': |
||
392 | //%X |
||
393 | //Locale specific 24-hour time format. The format for a 24-hour time in the default "C" locale for Unix/Mac is "%H:%M:%S". On Windows, this value is the locale specific time format, as specified in the Regional Options control panel settings. |
||
394 | result.Append( date.ToShortTimeString() ); |
||
395 | break; |
||
396 | case 'y': |
||
397 | //%y |
||
398 | //Year without century (00 - 99). |
||
399 | result.Append( date.ToString( "yy", formatInfo ) ); |
||
400 | break; |
||
401 | |||
402 | case 'Y': |
||
403 | //%Y |
||
404 | //Year with century (e.g. 1990) |
||
405 | result.Append( date.ToString( "yyyy", formatInfo ) ); |
||
406 | break; |
||
407 | case 'Z': |
||
408 | //%Z |
||
409 | //Time zone name. |
||
410 | result.Append( date.ToString( "zzz", formatInfo ) ); |
||
411 | break; |
||
412 | default: |
||
413 | result.Append( format[ix] ); |
||
414 | break; |
||
415 | } |
||
416 | } |
||
417 | else |
||
418 | { |
||
419 | result.Append( format[ix] ); |
||
420 | } |
||
421 | } |
||
422 | interp.setResult( result.ToString() ); |
||
423 | } |
||
424 | private int GetWeek( DateTime date, System.DayOfWeek firstDayOfWeek, bool iso ) |
||
425 | { |
||
426 | GregorianCalendar cal = new GregorianCalendar(); |
||
427 | CalendarWeekRule weekRule = CalendarWeekRule.FirstFullWeek; |
||
428 | if ( iso ) |
||
429 | { |
||
430 | firstDayOfWeek = System.DayOfWeek.Monday; |
||
431 | weekRule = CalendarWeekRule.FirstFourDayWeek; |
||
432 | } |
||
433 | return cal.GetWeekOfYear( date, weekRule, firstDayOfWeek ); |
||
434 | } |
||
435 | private void SetWeekday( TclDateTime calendar, ClockRelTimespan diff ) |
||
436 | // time difference to evaluate |
||
437 | { |
||
438 | int weekday = diff.getWeekday(); |
||
439 | int dayOrdinal = diff.DayOrdinal; |
||
440 | |||
441 | // ATK |
||
442 | // while (SupportClass.CalendarManager.manager.Get(calendar, SupportClass.CalendarManager.DAY_OF_WEEK) != weekday) |
||
443 | // { |
||
444 | // |
||
445 | // calendar.add(SupportClass.CalendarManager.DATE, 1); |
||
446 | // } |
||
447 | // if (dayOrdinal > 1) |
||
448 | // { |
||
449 | // |
||
450 | // calendar.add(SupportClass.CalendarManager.DATE, 7 * (dayOrdinal - 1)); |
||
451 | // } |
||
452 | } |
||
453 | private void SetOrdMonth( TclDateTime calendar, ClockRelTimespan diff ) |
||
454 | // time difference to evaluate |
||
455 | { |
||
456 | int month = diff.Months; |
||
457 | int ordMonth = diff.OrdMonth; |
||
458 | |||
459 | // calendar.add(SupportClass.CalendarManager.MONTH, 1); /* we want to get the next month... */ |
||
460 | // while (SupportClass.CalendarManager.manager.Get(calendar, SupportClass.CalendarManager.MONTH) != month) |
||
461 | // { |
||
462 | // calendar.add(SupportClass.CalendarManager.MONTH, 1); |
||
463 | // } |
||
464 | // if (ordMonth > 1) |
||
465 | // { |
||
466 | // calendar.add(SupportClass.CalendarManager.YEAR, ordMonth - 1); |
||
467 | // } |
||
468 | calendar.day = 1; |
||
469 | calendar.hour = 0; |
||
470 | calendar.minute = 0; |
||
471 | calendar.second = 0; |
||
472 | } |
||
473 | private System.DateTime GetDate( string dateString, System.DateTime baseDate, bool useGMT ) |
||
474 | { |
||
475 | if ( useGMT ) |
||
476 | { |
||
477 | baseDate = baseDate.ToUniversalTime(); |
||
478 | } |
||
479 | TclDateTime calendar = new TclDateTime(); |
||
480 | calendar.dateTime = baseDate; |
||
481 | calendar.hour = 0; |
||
482 | calendar.minute = 0; |
||
483 | calendar.second = 0; |
||
484 | calendar.millisecond = 0; |
||
485 | |||
486 | ClockToken[] dt = GetTokens( dateString, false ); |
||
487 | |||
488 | System.Int32 parsePos = 0; |
||
489 | ClockRelTimespan diff = new ClockRelTimespan(); |
||
490 | int hasTime = 0; |
||
491 | int hasZone = 0; |
||
492 | int hasDate = 0; |
||
493 | int hasDay = 0; |
||
494 | int hasOrdMonth = 0; |
||
495 | int hasRel = 0; |
||
496 | |||
497 | while ( parsePos < dt.Length ) |
||
498 | { |
||
499 | if ( ParseTime( dt, ref parsePos, calendar ) ) |
||
500 | { |
||
501 | hasTime++; |
||
502 | } |
||
503 | else if ( ParseZone( dt, ref parsePos, calendar ) ) |
||
504 | { |
||
505 | hasZone++; |
||
506 | } |
||
507 | else if ( ParseIso( dt, ref parsePos, calendar ) ) |
||
508 | { |
||
509 | hasDate++; |
||
510 | } |
||
511 | else if ( ParseDate( dt, ref parsePos, calendar ) ) |
||
512 | { |
||
513 | hasDate++; |
||
514 | } |
||
515 | else if ( ParseDay( dt, ref parsePos, diff ) ) |
||
516 | { |
||
517 | hasDay++; |
||
518 | } |
||
519 | else if ( ParseOrdMonth( dt, ref parsePos, diff ) ) |
||
520 | { |
||
521 | hasOrdMonth++; |
||
522 | } |
||
523 | else if ( ParseRelSpec( dt, ref parsePos, diff ) ) |
||
524 | { |
||
525 | hasRel++; |
||
526 | } |
||
527 | else if ( ParseNumber( dt, ref parsePos, calendar, hasDate > 0 && hasTime > 0 && hasRel == 0 ) ) |
||
528 | { |
||
529 | if ( hasDate == 0 || hasTime == 0 || hasRel > 0 ) |
||
530 | { |
||
531 | hasTime++; |
||
532 | } |
||
533 | } |
||
534 | else if ( ParseTrek( dt, ref parsePos, calendar ) ) |
||
535 | { |
||
536 | hasDate++; |
||
537 | hasTime++; |
||
538 | } |
||
539 | else |
||
540 | { |
||
541 | goto failed; |
||
542 | } |
||
543 | } |
||
544 | |||
545 | if ( hasTime > 1 || hasZone > 1 || hasDate > 1 || hasDay > 1 || hasOrdMonth > 1 ) |
||
546 | { |
||
547 | goto failed; |
||
548 | } |
||
549 | |||
550 | // The following line handles years that are specified using |
||
551 | // only two digits. The line of code below implements a policy |
||
552 | // defined by the X/Open workgroup on the millinium rollover. |
||
553 | // Note: some of those dates may not actually be valid on some |
||
554 | // platforms. The POSIX standard startes that the dates 70-99 |
||
555 | // shall refer to 1970-1999 and 00-38 shall refer to 2000-2038. |
||
556 | // This later definition should work on all platforms. |
||
557 | |||
558 | int thisYear = calendar.year; |
||
559 | if ( thisYear < 100 ) |
||
560 | { |
||
561 | if ( thisYear >= 69 ) |
||
562 | { |
||
563 | calendar.year = thisYear + 1900; |
||
564 | } |
||
565 | else |
||
566 | { |
||
567 | calendar.year = thisYear + 2000; |
||
568 | } |
||
569 | } |
||
570 | |||
571 | if ( hasRel > 0 ) |
||
572 | { |
||
573 | if ( hasTime == 0 && hasDate == 0 && hasDay == 0 ) |
||
574 | { |
||
575 | calendar.dateTime = baseDate; |
||
576 | } |
||
577 | // Certain JDK implementations are buggy WRT DST. |
||
578 | // Work around this issue by adding a day instead |
||
579 | // of a days worth of seconds. |
||
580 | int seconds_in_day = ( 60 * 60 * 24 ); |
||
581 | int seconds = diff.Seconds; |
||
582 | bool negative_seconds = ( seconds < 0 ); |
||
583 | int days = 0; |
||
584 | if ( negative_seconds ) |
||
585 | seconds *= ( -1 ); |
||
586 | while ( seconds >= seconds_in_day ) |
||
587 | { |
||
588 | seconds -= seconds_in_day; |
||
589 | days++; |
||
590 | } |
||
591 | if ( negative_seconds ) |
||
592 | { |
||
593 | seconds *= ( -1 ); |
||
594 | days *= ( -1 ); |
||
595 | } |
||
596 | if ( days != 0 ) |
||
597 | { |
||
598 | |||
599 | // calendar.add(SupportClass.CalendarManager.DATE, days); |
||
600 | } |
||
601 | if ( seconds != 0 ) |
||
602 | { |
||
603 | |||
604 | // calendar.add(SupportClass.CalendarManager.SECOND, seconds); |
||
605 | } |
||
606 | |||
607 | // calendar.add(SupportClass.CalendarManager.MONTH, diff.Months); |
||
608 | } |
||
609 | |||
610 | if ( hasDay > 0 && hasDate == 0 ) |
||
611 | { |
||
612 | SetWeekday( calendar, diff ); |
||
613 | } |
||
614 | |||
615 | if ( hasOrdMonth > 0 ) |
||
616 | { |
||
617 | SetOrdMonth( calendar, diff ); |
||
618 | } |
||
619 | try |
||
620 | { |
||
621 | return calendar.dateTime; |
||
622 | } |
||
623 | catch ( Exception ) |
||
624 | { |
||
625 | throw new FormatException(); |
||
626 | } |
||
627 | failed: |
||
628 | throw new FormatException(); |
||
629 | } |
||
630 | private bool ParseTime( ClockToken[] dt, ref System.Int32 parsePos, TclDateTime calendar ) |
||
631 | // calendar object to set |
||
632 | { |
||
633 | int pos = parsePos; |
||
634 | |||
635 | if ( pos + 6 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( ':' ) && dt[pos + 2].UNumber && dt[pos + 3].is_Renamed( ':' ) && dt[pos + 4].UNumber && dt[pos + 5].is_Renamed( '-' ) && dt[pos + 6].UNumber ) |
||
636 | { |
||
637 | ClockToken zone = GetTimeZoneFromRawOffset( ( -dt[pos + 6].Int ) / 100 ); |
||
638 | if ( zone != null ) |
||
639 | { |
||
640 | calendar.hour = dt[pos].Int; |
||
641 | calendar.minute = dt[pos + 2].Int; |
||
642 | calendar.second = dt[pos + 4].Int; |
||
643 | // TODO |
||
644 | // calendar.setTimeZone(zone.Zone); |
||
645 | parsePos = pos + 7; |
||
646 | return true; |
||
647 | } |
||
648 | } |
||
649 | if ( pos + 4 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( ':' ) && dt[pos + 2].UNumber && dt[pos + 3].is_Renamed( ':' ) && dt[pos + 4].UNumber ) |
||
650 | { |
||
651 | parsePos = pos + 5; |
||
652 | ParseMeridianAndSetHour( dt, ref parsePos, calendar, dt[pos].Int ); |
||
653 | calendar.minute = dt[pos + 2].Int; |
||
654 | calendar.second = dt[pos + 4].Int; |
||
655 | return true; |
||
656 | } |
||
657 | if ( pos + 4 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( ':' ) && dt[pos + 2].UNumber && dt[pos + 3].is_Renamed( '-' ) && dt[pos + 4].UNumber ) |
||
658 | { |
||
659 | ClockToken zone = GetTimeZoneFromRawOffset( ( -dt[pos + 4].Int ) / 100 ); |
||
660 | if ( zone != null ) |
||
661 | { |
||
662 | calendar.hour = dt[pos].Int; |
||
663 | calendar.minute = dt[pos + 2].Int; |
||
664 | |||
665 | // calendar.setTimeZone(zone.Zone); |
||
666 | parsePos = pos + 5; |
||
667 | return true; |
||
668 | } |
||
669 | } |
||
670 | if ( pos + 2 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( ':' ) && dt[pos + 2].UNumber ) |
||
671 | { |
||
672 | parsePos = pos + 3; |
||
673 | ParseMeridianAndSetHour( dt, ref parsePos, calendar, dt[pos].Int ); |
||
674 | calendar.minute = dt[pos + 2].Int; |
||
675 | return true; |
||
676 | } |
||
677 | if ( pos + 1 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( ClockToken.MERIDIAN ) ) |
||
678 | { |
||
679 | parsePos = pos + 1; |
||
680 | ParseMeridianAndSetHour( dt, ref parsePos, calendar, dt[pos].Int ); |
||
681 | return true; |
||
682 | } |
||
683 | return false; |
||
684 | } |
||
685 | private bool ParseZone( ClockToken[] dt, ref System.Int32 parsePos, TclDateTime calendar ) |
||
686 | // calendar object to set |
||
687 | { |
||
688 | int pos = parsePos; |
||
689 | |||
690 | if ( pos + 1 < dt.Length && dt[pos].is_Renamed( ClockToken.ZONE ) && dt[pos + 1].is_Renamed( ClockToken.DST ) ) |
||
691 | { |
||
692 | |||
693 | // calendar.setTimeZone(dt[pos].Zone); |
||
694 | parsePos = pos + 2; |
||
695 | return true; |
||
696 | } |
||
697 | if ( pos < dt.Length && dt[pos].is_Renamed( ClockToken.ZONE ) ) |
||
698 | { |
||
699 | |||
700 | // calendar.setTimeZone(dt[pos].Zone); |
||
701 | parsePos = pos + 1; |
||
702 | return true; |
||
703 | } |
||
704 | if ( pos < dt.Length && dt[pos].is_Renamed( ClockToken.DAYZONE ) ) |
||
705 | { |
||
706 | |||
707 | // calendar.setTimeZone(dt[pos].Zone); |
||
708 | parsePos = pos + 1; |
||
709 | return true; |
||
710 | } |
||
711 | return false; |
||
712 | } |
||
713 | private bool ParseDay( ClockToken[] dt, ref System.Int32 parsePos, ClockRelTimespan diff ) |
||
714 | // time difference to evaluate |
||
715 | { |
||
716 | int pos = parsePos; |
||
717 | |||
718 | if ( pos + 2 < dt.Length && dt[pos].is_Renamed( '+' ) && dt[pos + 1].UNumber && dt[pos + 2].is_Renamed( ClockToken.DAY ) ) |
||
719 | { |
||
720 | diff.setWeekday( dt[pos + 2].Int, dt[pos + 1].Int ); |
||
721 | parsePos = pos + 3; |
||
722 | return true; |
||
723 | } |
||
724 | if ( pos + 2 < dt.Length && dt[pos].is_Renamed( '-' ) && dt[pos + 1].UNumber && dt[pos + 2].is_Renamed( ClockToken.DAY ) ) |
||
725 | { |
||
726 | diff.setWeekday( dt[pos + 2].Int, -dt[pos + 1].Int ); |
||
727 | parsePos = pos + 3; |
||
728 | return true; |
||
729 | } |
||
730 | if ( pos + 1 < dt.Length && dt[pos].is_Renamed( ClockToken.NEXT ) && dt[pos + 1].is_Renamed( ClockToken.DAY ) ) |
||
731 | { |
||
732 | diff.setWeekday( dt[pos + 1].Int, 2 ); |
||
733 | parsePos = pos + 2; |
||
734 | return true; |
||
735 | } |
||
736 | if ( pos + 1 < dt.Length && dt[pos].is_Renamed( ClockToken.DAY ) && dt[pos + 1].is_Renamed( ',' ) ) |
||
737 | { |
||
738 | diff.setWeekday( dt[pos].Int ); |
||
739 | parsePos = pos + 2; |
||
740 | return true; |
||
741 | } |
||
742 | if ( pos + 1 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( ClockToken.DAY ) ) |
||
743 | { |
||
744 | diff.setWeekday( dt[pos + 1].Int, dt[pos].Int ); |
||
745 | parsePos = pos + 2; |
||
746 | return true; |
||
747 | } |
||
748 | if ( pos < dt.Length && dt[pos].is_Renamed( ClockToken.DAY ) ) |
||
749 | { |
||
750 | diff.setWeekday( dt[pos].Int ); |
||
751 | parsePos = pos + 1; |
||
752 | return true; |
||
753 | } |
||
754 | return false; |
||
755 | } |
||
756 | private bool ParseDate( ClockToken[] dt, ref System.Int32 parsePos, TclDateTime calendar ) |
||
757 | // calendar object to set |
||
758 | { |
||
759 | int pos = parsePos; |
||
760 | |||
761 | if ( pos + 4 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( '/' ) && dt[pos + 2].UNumber && dt[pos + 3].is_Renamed( '/' ) && dt[pos + 4].UNumber ) |
||
762 | { |
||
763 | calendar.day = dt[pos + 2].Int; |
||
764 | calendar.month = dt[pos].Int; |
||
765 | calendar.year = dt[pos + 4].Int; |
||
766 | parsePos = pos + 5; |
||
767 | return true; |
||
768 | } |
||
769 | if ( pos + 4 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( '-' ) && dt[pos + 2].is_Renamed( ClockToken.MONTH ) && dt[pos + 3].is_Renamed( '-' ) && dt[pos + 4].UNumber ) |
||
770 | { |
||
771 | calendar.year = dt[pos + 4].Int; |
||
772 | calendar.month = dt[pos + 2].Int; |
||
773 | calendar.day = dt[pos].Int; |
||
774 | parsePos = pos + 5; |
||
775 | return true; |
||
776 | } |
||
777 | if ( pos + 4 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( '-' ) && dt[pos + 2].UNumber && dt[pos + 3].is_Renamed( '-' ) && dt[pos + 4].UNumber ) |
||
778 | { |
||
779 | calendar.year = dt[pos].Int; |
||
780 | calendar.month = dt[pos + 2].Int; |
||
781 | calendar.day = dt[pos + 4].Int; |
||
782 | parsePos = pos + 5; |
||
783 | return true; |
||
784 | } |
||
785 | if ( pos + 3 < dt.Length && dt[pos].is_Renamed( ClockToken.MONTH ) && dt[pos + 1].UNumber && dt[pos + 2].is_Renamed( ',' ) && dt[pos + 3].UNumber ) |
||
786 | { |
||
787 | calendar.day = dt[pos + 1].Int; |
||
788 | calendar.month = dt[pos].Int; |
||
789 | calendar.year = dt[pos + 3].Int; |
||
790 | parsePos = pos + 4; |
||
791 | return true; |
||
792 | } |
||
793 | if ( pos + 2 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( '/' ) && dt[pos + 2].UNumber ) |
||
794 | { |
||
795 | calendar.day = dt[pos + 2].Int; |
||
796 | calendar.month = dt[pos].Int; |
||
797 | parsePos = pos + 3; |
||
798 | return true; |
||
799 | } |
||
800 | if ( pos + 2 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( ClockToken.MONTH ) && dt[pos + 2].UNumber ) |
||
801 | { |
||
802 | calendar.day = dt[pos].Int; |
||
803 | calendar.month = dt[pos + 1].Int; |
||
804 | calendar.year = dt[pos + 2].Int; |
||
805 | parsePos = pos + 3; |
||
806 | return true; |
||
807 | } |
||
808 | if ( pos + 1 < dt.Length && dt[pos].is_Renamed( ClockToken.MONTH ) && dt[pos + 1].UNumber ) |
||
809 | { |
||
810 | calendar.day = dt[pos + 1].Int; |
||
811 | calendar.month = dt[pos].Int; |
||
812 | parsePos = pos + 2; |
||
813 | return true; |
||
814 | } |
||
815 | if ( pos + 1 < dt.Length && dt[pos].UNumber && dt[pos + 1].is_Renamed( ClockToken.MONTH ) ) |
||
816 | { |
||
817 | calendar.day = dt[pos].Int; |
||
818 | calendar.month = dt[pos + 1].Int; |
||
819 | parsePos = pos + 2; |
||
820 | return true; |
||
821 | } |
||
822 | if ( pos < dt.Length && dt[pos].IsoBase ) |
||
823 | { |
||
824 | calendar.day = dt[pos].Int % 100; |
||
825 | calendar.month = ( dt[pos].Int % 10000 ) / 100; |
||
826 | calendar.year = dt[pos].Int / 10000; |
||
827 | parsePos = pos + 1; |
||
828 | return true; |
||
829 | } |
||
830 | if ( pos < dt.Length && dt[pos].is_Renamed( ClockToken.EPOCH ) ) |
||
831 | { |
||
832 | calendar.day = 1; |
||
833 | calendar.month = 0; |
||
834 | calendar.year = EPOCH_YEAR; |
||
835 | parsePos = pos + 1; |
||
836 | return true; |
||
837 | } |
||
838 | return false; |
||
839 | } |
||
840 | private bool ParseNumber( ClockToken[] dt, ref System.Int32 parsePos, TclDateTime calendar, bool mayBeYear ) |
||
841 | // number is considered to be year? |
||
842 | { |
||
843 | int pos = parsePos; |
||
844 | |||
845 | if ( pos < dt.Length && dt[pos].UNumber ) |
||
846 | { |
||
847 | parsePos = pos + 1; |
||
848 | if ( mayBeYear ) |
||
849 | { |
||
850 | calendar.year = dt[pos].Int; |
||
851 | } |
||
852 | else |
||
853 | { |
||
854 | calendar.hour = dt[pos].Int / 100; |
||
855 | calendar.minute = dt[pos].Int % 100; |
||
856 | calendar.second = 0; |
||
857 | } |
||
858 | return true; |
||
859 | } |
||
860 | return false; |
||
861 | } |
||
862 | private bool ParseRelSpec( ClockToken[] dt, ref System.Int32 parsePos, ClockRelTimespan diff ) |
||
863 | // time difference to evaluate |
||
864 | { |
||
865 | if ( !ParseRelUnits( dt, ref parsePos, diff ) ) |
||
866 | { |
||
867 | return false; |
||
868 | } |
||
869 | |||
870 | int pos = parsePos; |
||
871 | if ( pos < dt.Length && dt[pos].is_Renamed( ClockToken.AGO ) ) |
||
872 | { |
||
873 | diff.negate(); |
||
874 | parsePos = pos + 1; |
||
875 | } |
||
876 | return true; |
||
877 | } |
||
878 | private bool ParseRelUnits( ClockToken[] dt, ref System.Int32 parsePos, ClockRelTimespan diff ) |
||
879 | // time difference to evaluate |
||
880 | { |
||
881 | int pos = parsePos; |
||
882 | |||
883 | if ( pos + 2 < dt.Length && dt[pos].is_Renamed( '+' ) && dt[pos + 1].UNumber && dt[pos + 2].Unit ) |
||
884 | { |
||
885 | diff.addUnit( dt[pos + 2], dt[pos + 1].Int ); |
||
886 | parsePos = pos + 3; |
||
887 | return true; |
||
888 | } |
||
889 | if ( pos + 2 < dt.Length && dt[pos].is_Renamed( '-' ) && dt[pos + 1].UNumber && dt[pos + 2].Unit ) |
||
890 | { |
||
891 | diff.addUnit( dt[pos + 2], -dt[pos + 1].Int ); |
||
892 | parsePos = pos + 3; |
||
893 | return true; |
||
894 | } |
||
895 | if ( pos + 1 < dt.Length && dt[pos].UNumber && dt[pos + 1].Unit ) |
||
896 | { |
||
897 | diff.addUnit( dt[pos + 1], dt[pos].Int ); |
||
898 | parsePos = pos + 2; |
||
899 | return true; |
||
900 | } |
||
901 | else if ( pos + 2 < dt.Length && dt[pos].is_Renamed( ClockToken.NEXT ) && dt[pos + 1].UNumber && dt[pos + 2].Unit ) |
||
902 | { |
||
903 | diff.addUnit( dt[pos + 2], dt[pos + 1].Int ); |
||
904 | parsePos = pos + 3; |
||
905 | return true; |
||
906 | } |
||
907 | if ( pos + 1 < dt.Length && dt[pos].is_Renamed( ClockToken.NEXT ) && dt[pos + 1].Unit ) |
||
908 | { |
||
909 | diff.addUnit( dt[pos + 1] ); |
||
910 | parsePos = pos + 2; |
||
911 | return true; |
||
912 | } |
||
913 | if ( pos < dt.Length && dt[pos].Unit ) |
||
914 | { |
||
915 | diff.addUnit( dt[pos] ); |
||
916 | parsePos = pos + 1; |
||
917 | return true; |
||
918 | } |
||
919 | return false; |
||
920 | } |
||
921 | private bool ParseOrdMonth( ClockToken[] dt, ref System.Int32 parsePos, ClockRelTimespan diff ) |
||
922 | // time difference to evaluate |
||
923 | { |
||
924 | int pos = parsePos; |
||
925 | |||
926 | if ( pos + 2 < dt.Length && dt[pos].is_Renamed( ClockToken.NEXT ) && dt[pos + 1].UNumber && dt[pos + 2].is_Renamed( ClockToken.MONTH ) ) |
||
927 | { |
||
928 | diff.addOrdMonth( dt[pos + 2].Int, dt[pos + 1].Int ); |
||
929 | parsePos = pos + 3; |
||
930 | return true; |
||
931 | } |
||
932 | if ( pos + 1 < dt.Length && dt[pos].is_Renamed( ClockToken.NEXT ) && dt[pos + 1].is_Renamed( ClockToken.MONTH ) ) |
||
933 | { |
||
934 | diff.addOrdMonth( dt[pos + 1].Int, 1 ); |
||
935 | parsePos = pos + 2; |
||
936 | return true; |
||
937 | } |
||
938 | return false; |
||
939 | } |
||
940 | private bool ParseIso( ClockToken[] dt, ref System.Int32 parsePos, TclDateTime calendar ) |
||
941 | // calendar object to set |
||
942 | { |
||
943 | int pos = parsePos; |
||
944 | |||
945 | if ( pos + 6 < dt.Length && dt[pos].IsoBase && dt[pos + 1].is_Renamed( ClockToken.ZONE ) && dt[pos + 2].UNumber && dt[pos + 3].is_Renamed( ':' ) && dt[pos + 4].UNumber && dt[pos + 5].is_Renamed( ':' ) && dt[pos + 6].UNumber ) |
||
946 | { |
||
947 | calendar.day = dt[pos].Int % 100; |
||
948 | calendar.month = ( dt[pos].Int % 10000 ) / 100; |
||
949 | calendar.year = dt[pos].Int / 10000; |
||
950 | calendar.hour = dt[pos + 2].Int; |
||
951 | calendar.minute = dt[pos + 4].Int; |
||
952 | calendar.second = dt[pos + 6].Int; |
||
953 | parsePos = pos + 7; |
||
954 | return true; |
||
955 | } |
||
956 | if ( pos + 2 < dt.Length && dt[pos].IsoBase && dt[pos + 1].is_Renamed( ClockToken.ZONE ) && dt[pos + 1].Zone.GetUtcOffset( calendar.dateTime ).Hours == ( -7 ) * MILLIS_PER_HOUR && dt[pos + 2].IsoBase ) |
||
957 | { |
||
958 | calendar.day = dt[pos].Int % 100; |
||
959 | calendar.month = ( dt[pos].Int % 10000 ) / 100; |
||
960 | calendar.year = dt[pos].Int / 10000; |
||
961 | calendar.hour = dt[pos + 2].Int / 10000; |
||
962 | calendar.minute = ( dt[pos + 2].Int % 10000 ) / 100; |
||
963 | calendar.second = dt[pos + 2].Int % 100; |
||
964 | parsePos = pos + 3; |
||
965 | return true; |
||
966 | } |
||
967 | if ( pos + 1 < dt.Length && dt[pos].IsoBase && dt[pos + 1].IsoBase ) |
||
968 | { |
||
969 | calendar.day = dt[pos].Int % 100; |
||
970 | calendar.month = ( dt[pos].Int % 10000 ) / 100; |
||
971 | calendar.year = dt[pos].Int / 10000; |
||
972 | calendar.hour = dt[pos + 1].Int / 10000; |
||
973 | calendar.minute = ( dt[pos + 1].Int % 10000 ) / 100; |
||
974 | calendar.second = dt[pos + 1].Int % 100; |
||
975 | parsePos = pos + 2; |
||
976 | return true; |
||
977 | } |
||
978 | return false; |
||
979 | } |
||
980 | private bool ParseTrek( ClockToken[] dt, ref System.Int32 parsePos, TclDateTime calendar ) |
||
981 | // calendar object to set |
||
982 | { |
||
983 | int pos = parsePos; |
||
984 | |||
985 | if ( pos + 3 < dt.Length && dt[pos].is_Renamed( ClockToken.STARDATE ) && dt[pos + 1].UNumber && dt[pos + 2].is_Renamed( '.' ) && dt[pos + 3].UNumber ) |
||
986 | { |
||
987 | GregorianCalendar gcal = new GregorianCalendar(); |
||
988 | int trekYear = dt[pos + 1].Int / 1000 + 2323 - 377; |
||
989 | int trekDay = 1 + ( ( dt[pos + 1].Int % 1000 ) * ( gcal.IsLeapYear( trekYear ) ? 366 : 365 ) ) / 1000; |
||
990 | int trekSeconds = dt[pos + 3].Int * 144 * 60; |
||
991 | calendar.year = trekYear; |
||
992 | calendar.dateTime = gcal.AddDays( calendar.dateTime, trekDay ); |
||
993 | calendar.second = trekSeconds; |
||
994 | parsePos = pos + 4; |
||
995 | return true; |
||
996 | } |
||
997 | return false; |
||
998 | } |
||
999 | private void ParseMeridianAndSetHour( ClockToken[] dt, ref System.Int32 parsePos, TclDateTime calendar, int hour ) |
||
1000 | // hour value (1-12 or 0-23) to set. |
||
1001 | { |
||
1002 | int pos = parsePos; |
||
1003 | int hourField; |
||
1004 | |||
1005 | if ( pos < dt.Length && dt[pos].is_Renamed( ClockToken.MERIDIAN ) ) |
||
1006 | { |
||
1007 | // SupportClass.CalendarManager.manager.Set(calendar, SupportClass.CalendarManager.AM_PM, dt[pos].Int); |
||
1008 | parsePos = pos + 1; |
||
1009 | hourField = SupportClass.CalendarManager.HOUR; |
||
1010 | } |
||
1011 | else |
||
1012 | { |
||
1013 | hourField = SupportClass.CalendarManager.HOUR_OF_DAY; |
||
1014 | } |
||
1015 | |||
1016 | if ( hourField == SupportClass.CalendarManager.HOUR && hour == 12 ) |
||
1017 | { |
||
1018 | hour = 0; |
||
1019 | } |
||
1020 | calendar.hour = hour; |
||
1021 | } |
||
1022 | private ClockToken[] GetTokens( string in_Renamed, bool debug ) |
||
1023 | // Send the generated token list to stderr? |
||
1024 | { |
||
1025 | System.Int32 parsePos = 0; |
||
1026 | ClockToken dt; |
||
1027 | ArrayList tokenVector = new ArrayList( in_Renamed.Length ); |
||
1028 | |||
1029 | while ( ( dt = GetNextToken( in_Renamed, ref parsePos ) ) != null ) |
||
1030 | { |
||
1031 | tokenVector.Add( dt ); |
||
1032 | } |
||
1033 | |||
1034 | ClockToken[] tokenArray = new ClockToken[tokenVector.Count]; |
||
1035 | tokenVector.CopyTo( tokenArray ); |
||
1036 | |||
1037 | #if DEBUG |
||
1038 | for ( int ix = 0; ix < tokenArray.Length; ix++ ) |
||
1039 | { |
||
1040 | if ( ix != 0 ) |
||
1041 | { |
||
1042 | System.Console.Error.Write( "," ); |
||
1043 | } |
||
1044 | |||
1045 | System.Console.Error.Write( tokenArray[ix].ToString() ); |
||
1046 | } |
||
1047 | System.Console.Error.WriteLine( "" ); |
||
1048 | #endif |
||
1049 | |||
1050 | return tokenArray; |
||
1051 | } |
||
1052 | private ClockToken GetNextToken( string in_Renamed, ref System.Int32 parsePos ) |
||
1053 | // Current position in input |
||
1054 | { |
||
1055 | int pos = parsePos; |
||
1056 | int sign; |
||
1057 | |||
1058 | while ( true ) |
||
1059 | { |
||
1060 | while ( pos < in_Renamed.Length && ( System.Char.GetUnicodeCategory( in_Renamed[pos] ) == System.Globalization.UnicodeCategory.SpaceSeparator ) ) |
||
1061 | { |
||
1062 | pos++; |
||
1063 | } |
||
1064 | if ( pos >= in_Renamed.Length ) |
||
1065 | { |
||
1066 | break; |
||
1067 | } |
||
1068 | |||
1069 | char c = in_Renamed[pos]; |
||
1070 | if ( System.Char.IsDigit( c ) ) |
||
1071 | { |
||
1072 | int number = 0; |
||
1073 | int count = 0; |
||
1074 | while ( pos < in_Renamed.Length && System.Char.IsDigit( c = in_Renamed[pos] ) ) |
||
1075 | { |
||
1076 | number = 10 * number + c - '0'; |
||
1077 | pos++; |
||
1078 | count++; |
||
1079 | } |
||
1080 | parsePos = pos; |
||
1081 | return new ClockToken( number, count >= 6 ); |
||
1082 | } |
||
1083 | if ( System.Char.IsLetter( c ) ) |
||
1084 | { |
||
1085 | int beginPos = pos; |
||
1086 | while ( ++pos < in_Renamed.Length ) |
||
1087 | { |
||
1088 | c = in_Renamed[pos]; |
||
1089 | if ( !System.Char.IsLetter( c ) && c != '.' ) |
||
1090 | { |
||
1091 | break; |
||
1092 | } |
||
1093 | } |
||
1094 | parsePos = pos; |
||
1095 | return LookupWord( in_Renamed.Substring( beginPos, ( pos ) - ( beginPos ) ) ); |
||
1096 | } |
||
1097 | parsePos = pos + 1; |
||
1098 | return new ClockToken( in_Renamed[pos] ); |
||
1099 | } |
||
1100 | parsePos = pos + 1; |
||
1101 | return null; |
||
1102 | } |
||
1103 | private ClockToken LookupWord( string word ) |
||
1104 | // word to lookup |
||
1105 | { |
||
1106 | int ix; |
||
1107 | string[] names; |
||
1108 | string[][] zones; |
||
1109 | |||
1110 | if ( word.ToUpper().Equals( "am".ToUpper() ) || word.ToUpper().Equals( "a.m.".ToUpper() ) ) |
||
1111 | { |
||
1112 | return new ClockToken( ClockToken.MERIDIAN, SupportClass.CalendarManager.AM ); |
||
1113 | } |
||
1114 | if ( word.ToUpper().Equals( "pm".ToUpper() ) || word.ToUpper().Equals( "p.m.".ToUpper() ) ) |
||
1115 | { |
||
1116 | return new ClockToken( ClockToken.MERIDIAN, SupportClass.CalendarManager.PM ); |
||
1117 | } |
||
1118 | |||
1119 | // See if we have an abbreviation for a day or month. |
||
1120 | |||
1121 | bool abbrev; |
||
1122 | if ( word.Length == 3 ) |
||
1123 | { |
||
1124 | abbrev = true; |
||
1125 | } |
||
1126 | else if ( word.Length == 4 && word[3] == '.' ) |
||
1127 | { |
||
1128 | abbrev = true; |
||
1129 | word = word.Substring( 0, ( 3 ) - ( 0 ) ); |
||
1130 | } |
||
1131 | else |
||
1132 | { |
||
1133 | abbrev = false; |
||
1134 | } |
||
1135 | |||
1136 | |||
1137 | DateTimeFormatInfo symbols = new CultureInfo( "en-US" ).DateTimeFormat; |
||
1138 | if ( abbrev ) |
||
1139 | { |
||
1140 | names = symbols.AbbreviatedMonthNames; |
||
1141 | } |
||
1142 | else |
||
1143 | { |
||
1144 | names = (string[])symbols.MonthNames; |
||
1145 | } |
||
1146 | for ( ix = 0; ix < names.Length; ix++ ) |
||
1147 | { |
||
1148 | if ( word.ToUpper().Equals( names[ix].ToUpper() ) ) |
||
1149 | { |
||
1150 | return new ClockToken( ClockToken.MONTH, ix + 1 ); |
||
1151 | } |
||
1152 | } |
||
1153 | if ( abbrev ) |
||
1154 | { |
||
1155 | names = symbols.AbbreviatedDayNames; |
||
1156 | } |
||
1157 | else |
||
1158 | { |
||
1159 | names = symbols.DayNames; |
||
1160 | } |
||
1161 | for ( ix = 0; ix < names.Length; ix++ ) |
||
1162 | { |
||
1163 | if ( word.ToUpper().Equals( names[ix].ToUpper() ) ) |
||
1164 | { |
||
1165 | return new ClockToken( ClockToken.DAY, ix ); |
||
1166 | } |
||
1167 | } |
||
1168 | |||
1169 | // Drop out any periods and try the timezone table. |
||
1170 | |||
1171 | StringBuilder withoutDotsBuf = new StringBuilder( word.Length ); |
||
1172 | for ( ix = 0; ix < word.Length; ix++ ) |
||
1173 | { |
||
1174 | if ( word[ix] != '.' ) |
||
1175 | { |
||
1176 | withoutDotsBuf.Append( word[ix] ); |
||
1177 | } |
||
1178 | } |
||
1179 | |||
1180 | string withoutDots = new string( withoutDotsBuf.ToString().ToCharArray() ); |
||
1181 | |||
1182 | // zones = symbols.getZoneStrings(); |
||
1183 | |||
1184 | // for (ix = 0; ix < zones.Length; ix++) |
||
1185 | // { |
||
1186 | // if (withoutDots.ToUpper().Equals(zones[ix][2].ToUpper()) || withoutDots.ToUpper().Equals(zones[ix][4].ToUpper())) |
||
1187 | // { |
||
1188 | // |
||
1189 | // System.TimeZone zone = TimeZone.getTimeZone(zones[ix][0]); |
||
1190 | // return new ClockToken(ClockToken.ZONE, zone); |
||
1191 | // } |
||
1192 | // } |
||
1193 | if ( withoutDots.ToUpper().Equals( "dst".ToUpper() ) ) |
||
1194 | { |
||
1195 | return new ClockToken( ClockToken.DST, null ); |
||
1196 | } |
||
1197 | |||
1198 | // Strip off any plural and try the units. |
||
1199 | |||
1200 | string singular; |
||
1201 | if ( word.EndsWith( "s" ) ) |
||
1202 | { |
||
1203 | singular = word.Substring( 0, ( word.Length - 1 ) - ( 0 ) ); |
||
1204 | } |
||
1205 | else |
||
1206 | { |
||
1207 | singular = word; |
||
1208 | } |
||
1209 | if ( singular.ToUpper().Equals( "year".ToUpper() ) ) |
||
1210 | { |
||
1211 | return new ClockToken( ClockToken.MONTH_UNIT, 12 ); |
||
1212 | } |
||
1213 | else if ( singular.ToUpper().Equals( "month".ToUpper() ) ) |
||
1214 | { |
||
1215 | return new ClockToken( ClockToken.MONTH_UNIT, 1 ); |
||
1216 | } |
||
1217 | else if ( singular.ToUpper().Equals( "fortnight".ToUpper() ) ) |
||
1218 | { |
||
1219 | return new ClockToken( ClockToken.MINUTE_UNIT, 14 * 24 * 60 ); |
||
1220 | } |
||
1221 | else if ( singular.ToUpper().Equals( "week".ToUpper() ) ) |
||
1222 | { |
||
1223 | return new ClockToken( ClockToken.MINUTE_UNIT, 7 * 24 * 60 ); |
||
1224 | } |
||
1225 | else if ( singular.ToUpper().Equals( "day".ToUpper() ) ) |
||
1226 | { |
||
1227 | return new ClockToken( ClockToken.MINUTE_UNIT, 24 * 60 ); |
||
1228 | } |
||
1229 | else if ( singular.ToUpper().Equals( "hour".ToUpper() ) ) |
||
1230 | { |
||
1231 | return new ClockToken( ClockToken.MINUTE_UNIT, 60 ); |
||
1232 | } |
||
1233 | else if ( singular.ToUpper().Equals( "minute".ToUpper() ) ) |
||
1234 | { |
||
1235 | return new ClockToken( ClockToken.MINUTE_UNIT, 1 ); |
||
1236 | } |
||
1237 | else if ( singular.ToUpper().Equals( "min".ToUpper() ) ) |
||
1238 | { |
||
1239 | return new ClockToken( ClockToken.MINUTE_UNIT, 1 ); |
||
1240 | } |
||
1241 | else if ( singular.ToUpper().Equals( "second".ToUpper() ) ) |
||
1242 | { |
||
1243 | return new ClockToken( ClockToken.SEC_UNIT, 1 ); |
||
1244 | } |
||
1245 | else if ( singular.ToUpper().Equals( "sec".ToUpper() ) ) |
||
1246 | { |
||
1247 | return new ClockToken( ClockToken.SEC_UNIT, 1 ); |
||
1248 | } |
||
1249 | |||
1250 | if ( singular.ToUpper().Equals( "tomorrow".ToUpper() ) ) |
||
1251 | { |
||
1252 | return new ClockToken( ClockToken.MINUTE_UNIT, 1 * 24 * 60 ); |
||
1253 | } |
||
1254 | else if ( singular.ToUpper().Equals( "yesterday".ToUpper() ) ) |
||
1255 | { |
||
1256 | return new ClockToken( ClockToken.MINUTE_UNIT, ( -1 ) * 24 * 60 ); |
||
1257 | } |
||
1258 | else if ( singular.ToUpper().Equals( "today".ToUpper() ) ) |
||
1259 | { |
||
1260 | return new ClockToken( ClockToken.MINUTE_UNIT, 0 ); |
||
1261 | } |
||
1262 | else if ( singular.ToUpper().Equals( "now".ToUpper() ) ) |
||
1263 | { |
||
1264 | return new ClockToken( ClockToken.MINUTE_UNIT, 0 ); |
||
1265 | } |
||
1266 | else if ( singular.ToUpper().Equals( "last".ToUpper() ) ) |
||
1267 | { |
||
1268 | return new ClockToken( -1, false ); |
||
1269 | } |
||
1270 | else if ( singular.ToUpper().Equals( "this".ToUpper() ) ) |
||
1271 | { |
||
1272 | return new ClockToken( ClockToken.MINUTE_UNIT, 0 ); |
||
1273 | } |
||
1274 | else if ( singular.ToUpper().Equals( "next".ToUpper() ) ) |
||
1275 | { |
||
1276 | return new ClockToken( ClockToken.NEXT, 1 ); |
||
1277 | } |
||
1278 | else if ( singular.ToUpper().Equals( "ago".ToUpper() ) ) |
||
1279 | { |
||
1280 | return new ClockToken( ClockToken.AGO, 1 ); |
||
1281 | } |
||
1282 | else if ( singular.ToUpper().Equals( "epoch".ToUpper() ) ) |
||
1283 | { |
||
1284 | return new ClockToken( ClockToken.EPOCH, 0 ); |
||
1285 | } |
||
1286 | else if ( singular.ToUpper().Equals( "stardate".ToUpper() ) ) |
||
1287 | { |
||
1288 | return new ClockToken( ClockToken.STARDATE, 0 ); |
||
1289 | } |
||
1290 | |||
1291 | // Since a military timezone (T) is used in the clock test of 8.3, |
||
1292 | // we can't ignore these timezones any longer... |
||
1293 | |||
1294 | if ( withoutDots.Length == 1 ) |
||
1295 | { |
||
1296 | int rawOffset = 0; |
||
1297 | bool found = true; |
||
1298 | char milTz = System.Char.ToLower( withoutDots[0] ); |
||
1299 | |||
1300 | if ( milTz >= 'a' && milTz <= 'm' ) |
||
1301 | { |
||
1302 | rawOffset = milTz - 'a' + 1; |
||
1303 | } |
||
1304 | else if ( milTz >= 'n' && milTz < 'z' ) |
||
1305 | { |
||
1306 | rawOffset = 'n' - milTz - 1; |
||
1307 | } |
||
1308 | else if ( milTz != 'z' ) |
||
1309 | { |
||
1310 | found = false; |
||
1311 | } |
||
1312 | if ( found ) |
||
1313 | { |
||
1314 | ClockToken zone = GetTimeZoneFromRawOffset( rawOffset ); |
||
1315 | if ( zone != null ) |
||
1316 | { |
||
1317 | return zone; |
||
1318 | } |
||
1319 | } |
||
1320 | } |
||
1321 | |||
1322 | return new ClockToken( word ); |
||
1323 | } |
||
1324 | private ClockToken GetTimeZoneFromRawOffset( int rawOffset ) |
||
1325 | { |
||
1326 | |||
1327 | // string[] tzNames = TimeZone.getAvailableIDs(rawOffset * MILLIS_PER_HOUR); |
||
1328 | |||
1329 | // if (tzNames.Length > 0) |
||
1330 | // { |
||
1331 | // |
||
1332 | // System.TimeZone zone = TimeZone.getTimeZone(tzNames[0]); |
||
1333 | // return new ClockToken(ClockToken.ZONE, zone); |
||
1334 | // } |
||
1335 | return null; |
||
1336 | } |
||
1337 | } // end ClockCmd |
||
1338 | class ClockToken |
||
1339 | { |
||
1340 | public bool UNumber |
||
1341 | { |
||
1342 | get |
||
1343 | { |
||
1344 | return kind == UNUMBER; |
||
1345 | } |
||
1346 | |||
1347 | } |
||
1348 | public bool IsoBase |
||
1349 | { |
||
1350 | get |
||
1351 | { |
||
1352 | return kind == ISOBASE; |
||
1353 | } |
||
1354 | |||
1355 | } |
||
1356 | public bool Unit |
||
1357 | { |
||
1358 | get |
||
1359 | { |
||
1360 | return kind == MINUTE_UNIT || kind == MONTH_UNIT || kind == SEC_UNIT; |
||
1361 | } |
||
1362 | |||
1363 | } |
||
1364 | internal int Int |
||
1365 | { |
||
1366 | get |
||
1367 | { |
||
1368 | return number; |
||
1369 | } |
||
1370 | |||
1371 | } |
||
1372 | internal System.TimeZone Zone |
||
1373 | { |
||
1374 | get |
||
1375 | { |
||
1376 | return zone; |
||
1377 | } |
||
1378 | |||
1379 | } |
||
1380 | internal const int ISOBASE = 1; |
||
1381 | internal const int UNUMBER = 2; |
||
1382 | internal const int WORD = 3; |
||
1383 | internal const int CHAR = 4; |
||
1384 | internal const int MONTH = 5; |
||
1385 | internal const int DAY = 6; |
||
1386 | internal const int MONTH_UNIT = 7; |
||
1387 | internal const int MINUTE_UNIT = 8; |
||
1388 | internal const int SEC_UNIT = 9; |
||
1389 | internal const int AGO = 10; |
||
1390 | internal const int EPOCH = 11; |
||
1391 | internal const int ZONE = 12; |
||
1392 | internal const int DAYZONE = 13; |
||
1393 | internal const int DST = 14; |
||
1394 | internal const int MERIDIAN = 15; |
||
1395 | internal const int NEXT = 16; |
||
1396 | internal const int STARDATE = 17; |
||
1397 | |||
1398 | internal ClockToken( int number, bool isIsoBase ) |
||
1399 | { |
||
1400 | this.kind = isIsoBase ? ISOBASE : UNUMBER; |
||
1401 | this.number = number; |
||
1402 | } |
||
1403 | internal ClockToken( int kind, int number ) |
||
1404 | { |
||
1405 | this.kind = kind; |
||
1406 | this.number = number; |
||
1407 | } |
||
1408 | internal ClockToken( int kind, System.TimeZone zone ) |
||
1409 | { |
||
1410 | this.kind = kind; |
||
1411 | this.zone = zone; |
||
1412 | } |
||
1413 | internal ClockToken( string word ) |
||
1414 | { |
||
1415 | this.kind = WORD; |
||
1416 | this.word = word; |
||
1417 | } |
||
1418 | internal ClockToken( char c ) |
||
1419 | { |
||
1420 | this.kind = CHAR; |
||
1421 | this.c = c; |
||
1422 | } |
||
1423 | public bool is_Renamed( char c ) |
||
1424 | { |
||
1425 | return this.kind == CHAR && this.c == c; |
||
1426 | } |
||
1427 | public bool is_Renamed( int kind ) |
||
1428 | { |
||
1429 | return this.kind == kind; |
||
1430 | } |
||
1431 | |||
1432 | public override string ToString() |
||
1433 | { |
||
1434 | if ( UNumber ) |
||
1435 | { |
||
1436 | return "U" + System.Convert.ToString( Int ); |
||
1437 | } |
||
1438 | else if ( IsoBase ) |
||
1439 | { |
||
1440 | return "I" + System.Convert.ToString( Int ); |
||
1441 | } |
||
1442 | else if ( kind == WORD ) |
||
1443 | { |
||
1444 | return word; |
||
1445 | } |
||
1446 | else if ( kind == CHAR ) |
||
1447 | { |
||
1448 | return c.ToString(); |
||
1449 | } |
||
1450 | else if ( kind == ZONE || kind == DAYZONE ) |
||
1451 | { |
||
1452 | return zone.StandardName; |
||
1453 | } |
||
1454 | else |
||
1455 | { |
||
1456 | return "(" + kind + "," + Int + ")"; |
||
1457 | } |
||
1458 | } |
||
1459 | |||
1460 | private int kind; |
||
1461 | private int number; |
||
1462 | private string word; |
||
1463 | private char c; |
||
1464 | private System.TimeZone zone; |
||
1465 | } // end ClockToken |
||
1466 | class ClockRelTimespan |
||
1467 | { |
||
1468 | internal int Seconds |
||
1469 | { |
||
1470 | get |
||
1471 | { |
||
1472 | return seconds; |
||
1473 | } |
||
1474 | |||
1475 | } |
||
1476 | internal int Months |
||
1477 | { |
||
1478 | get |
||
1479 | { |
||
1480 | return months; |
||
1481 | } |
||
1482 | |||
1483 | } |
||
1484 | internal int OrdMonth |
||
1485 | { |
||
1486 | get |
||
1487 | { |
||
1488 | return ordMonth; |
||
1489 | } |
||
1490 | |||
1491 | } |
||
1492 | internal int DayOrdinal |
||
1493 | { |
||
1494 | get |
||
1495 | { |
||
1496 | return dayOrdinal; |
||
1497 | } |
||
1498 | |||
1499 | } |
||
1500 | internal ClockRelTimespan() |
||
1501 | { |
||
1502 | seconds = 0; |
||
1503 | months = 0; |
||
1504 | ordMonth = 0; |
||
1505 | weekday = 0; |
||
1506 | dayOrdinal = 0; |
||
1507 | } |
||
1508 | internal void addSeconds( int s ) |
||
1509 | { |
||
1510 | seconds += s; |
||
1511 | } |
||
1512 | internal void addMonths( int m ) |
||
1513 | { |
||
1514 | months += m; |
||
1515 | } |
||
1516 | internal void addOrdMonth( int m, int c ) |
||
1517 | { |
||
1518 | months = m; |
||
1519 | ordMonth += c; |
||
1520 | } |
||
1521 | internal void addUnit( ClockToken unit, int amount ) |
||
1522 | { |
||
1523 | if ( unit.is_Renamed( ClockToken.SEC_UNIT ) ) |
||
1524 | { |
||
1525 | addSeconds( unit.Int * amount ); |
||
1526 | } |
||
1527 | else if ( unit.is_Renamed( ClockToken.MINUTE_UNIT ) ) |
||
1528 | { |
||
1529 | addSeconds( unit.Int * 60 * amount ); |
||
1530 | } |
||
1531 | else if ( unit.is_Renamed( ClockToken.MONTH_UNIT ) ) |
||
1532 | { |
||
1533 | addMonths( unit.Int * amount ); |
||
1534 | } |
||
1535 | } |
||
1536 | internal void addUnit( ClockToken unit ) |
||
1537 | { |
||
1538 | addUnit( unit, 1 ); |
||
1539 | } |
||
1540 | internal void setWeekday( int w, int ord ) |
||
1541 | { |
||
1542 | weekday = w; |
||
1543 | dayOrdinal = ord; |
||
1544 | } |
||
1545 | internal void setWeekday( int w ) |
||
1546 | { |
||
1547 | setWeekday( w, 1 ); |
||
1548 | } |
||
1549 | internal void negate() |
||
1550 | { |
||
1551 | seconds = -seconds; |
||
1552 | months = -months; |
||
1553 | } |
||
1554 | internal int getWeekday() |
||
1555 | { |
||
1556 | return weekday; |
||
1557 | } |
||
1558 | private int seconds; |
||
1559 | private int months; |
||
1560 | private int ordMonth; |
||
1561 | private int weekday; |
||
1562 | private int dayOrdinal; |
||
1563 | } |
||
1564 | class TclDateTime |
||
1565 | { |
||
1566 | public int year, month, day, hour, minute, second, millisecond; |
||
1567 | public DateTime dateTime |
||
1568 | { |
||
1569 | get |
||
1570 | { |
||
1571 | return new DateTime( year, month, day, hour, minute, second, millisecond ); |
||
1572 | } |
||
1573 | set |
||
1574 | { |
||
1575 | DateTime dt = value; |
||
1576 | year = dt.Year; |
||
1577 | month = dt.Month; |
||
1578 | day = dt.Day; |
||
1579 | hour = dt.Hour; |
||
1580 | minute = dt.Minute; |
||
1581 | second = dt.Second; |
||
1582 | millisecond = dt.Millisecond; |
||
1583 | } |
||
1584 | } |
||
1585 | } |
||
1586 | } |