Mercurial > hg > audiodb
comparison bindings/as3/ext/com/adobe/utils/DateUtil.as @ 732:3a0b9700b3d2
* Initial AS3 commit
author | mas01mj |
---|---|
date | Tue, 14 Sep 2010 16:47:10 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
731:65134dd772fc | 732:3a0b9700b3d2 |
---|---|
1 /* | |
2 Copyright (c) 2008, Adobe Systems Incorporated | |
3 All rights reserved. | |
4 | |
5 Redistribution and use in source and binary forms, with or without | |
6 modification, are permitted provided that the following conditions are | |
7 met: | |
8 | |
9 * Redistributions of source code must retain the above copyright notice, | |
10 this list of conditions and the following disclaimer. | |
11 | |
12 * Redistributions in binary form must reproduce the above copyright | |
13 notice, this list of conditions and the following disclaimer in the | |
14 documentation and/or other materials provided with the distribution. | |
15 | |
16 * Neither the name of Adobe Systems Incorporated nor the names of its | |
17 contributors may be used to endorse or promote products derived from | |
18 this software without specific prior written permission. | |
19 | |
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | |
21 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, | |
22 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
23 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
24 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
25 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
26 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
27 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
28 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
29 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 */ | |
32 | |
33 package com.adobe.utils | |
34 { | |
35 import mx.formatters.DateBase; | |
36 | |
37 /** | |
38 * Class that contains static utility methods for manipulating and working | |
39 * with Dates. | |
40 * | |
41 * @langversion ActionScript 3.0 | |
42 * @playerversion Flash 9.0 | |
43 * @tiptext | |
44 */ | |
45 public class DateUtil | |
46 { | |
47 | |
48 /** | |
49 * Returns the English Short Month name (3 letters) for the Month that | |
50 * the Date represents. | |
51 * | |
52 * @param d The Date instance whose month will be used to retrieve the | |
53 * short month name. | |
54 * | |
55 * @return An English 3 Letter Month abbreviation. | |
56 * | |
57 * @langversion ActionScript 3.0 | |
58 * @playerversion Flash 9.0 | |
59 * @tiptext | |
60 * | |
61 * @see SHORT_MONTH | |
62 */ | |
63 public static function getShortMonthName(d:Date):String | |
64 { | |
65 return DateBase.monthNamesShort[d.getMonth()]; | |
66 } | |
67 | |
68 /** | |
69 * Returns the index of the month that the short month name string | |
70 * represents. | |
71 * | |
72 * @param m The 3 letter abbreviation representing a short month name. | |
73 * | |
74 * @param Optional parameter indicating whether the search should be case | |
75 * sensitive | |
76 * | |
77 * @return A int that represents that month represented by the specifed | |
78 * short name. | |
79 * | |
80 * @langversion ActionScript 3.0 | |
81 * @playerversion Flash 9.0 | |
82 * @tiptext | |
83 * | |
84 * @see SHORT_MONTH | |
85 */ | |
86 public static function getShortMonthIndex(m:String):int | |
87 { | |
88 return DateBase.monthNamesShort.indexOf(m); | |
89 } | |
90 | |
91 /** | |
92 * Returns the English full Month name for the Month that | |
93 * the Date represents. | |
94 * | |
95 * @param d The Date instance whose month will be used to retrieve the | |
96 * full month name. | |
97 * | |
98 * @return An English full month name. | |
99 * | |
100 * @langversion ActionScript 3.0 | |
101 * @playerversion Flash 9.0 | |
102 * @tiptext | |
103 * | |
104 * @see FULL_MONTH | |
105 */ | |
106 public static function getFullMonthName(d:Date):String | |
107 { | |
108 return DateBase.monthNamesLong[d.getMonth()]; | |
109 } | |
110 | |
111 /** | |
112 * Returns the index of the month that the full month name string | |
113 * represents. | |
114 * | |
115 * @param m A full month name. | |
116 * | |
117 * @return A int that represents that month represented by the specifed | |
118 * full month name. | |
119 * | |
120 * @langversion ActionScript 3.0 | |
121 * @playerversion Flash 9.0 | |
122 * @tiptext | |
123 * | |
124 * @see FULL_MONTH | |
125 */ | |
126 public static function getFullMonthIndex(m:String):int | |
127 { | |
128 return DateBase.monthNamesLong.indexOf(m); | |
129 } | |
130 | |
131 /** | |
132 * Returns the English Short Day name (3 letters) for the day that | |
133 * the Date represents. | |
134 * | |
135 * @param d The Date instance whose day will be used to retrieve the | |
136 * short day name. | |
137 * | |
138 * @return An English 3 Letter day abbreviation. | |
139 * | |
140 * @langversion ActionScript 3.0 | |
141 * @playerversion Flash 9.0 | |
142 * @tiptext | |
143 * | |
144 * @see SHORT_DAY | |
145 */ | |
146 public static function getShortDayName(d:Date):String | |
147 { | |
148 return DateBase.dayNamesShort[d.getDay()]; | |
149 } | |
150 | |
151 /** | |
152 * Returns the index of the day that the short day name string | |
153 * represents. | |
154 * | |
155 * @param m A short day name. | |
156 * | |
157 * @return A int that represents that short day represented by the specifed | |
158 * full month name. | |
159 * | |
160 * @langversion ActionScript 3.0 | |
161 * @playerversion Flash 9.0 | |
162 * @tiptext | |
163 * | |
164 * @see SHORT_DAY | |
165 */ | |
166 public static function getShortDayIndex(d:String):int | |
167 { | |
168 return DateBase.dayNamesShort.indexOf(d); | |
169 } | |
170 | |
171 /** | |
172 * Returns the English full day name for the day that | |
173 * the Date represents. | |
174 * | |
175 * @param d The Date instance whose day will be used to retrieve the | |
176 * full day name. | |
177 * | |
178 * @return An English full day name. | |
179 * | |
180 * @langversion ActionScript 3.0 | |
181 * @playerversion Flash 9.0 | |
182 * @tiptext | |
183 * | |
184 * @see FULL_DAY | |
185 */ | |
186 public static function getFullDayName(d:Date):String | |
187 { | |
188 return DateBase.dayNamesLong[d.getDay()]; | |
189 } | |
190 | |
191 /** | |
192 * Returns the index of the day that the full day name string | |
193 * represents. | |
194 * | |
195 * @param m A full day name. | |
196 * | |
197 * @return A int that represents that full day represented by the specifed | |
198 * full month name. | |
199 * | |
200 * @langversion ActionScript 3.0 | |
201 * @playerversion Flash 9.0 | |
202 * @tiptext | |
203 * | |
204 * @see FULL_DAY | |
205 */ | |
206 public static function getFullDayIndex(d:String):int | |
207 { | |
208 return DateBase.dayNamesLong.indexOf(d); | |
209 } | |
210 | |
211 /** | |
212 * Returns a two digit representation of the year represented by the | |
213 * specified date. | |
214 * | |
215 * @param d The Date instance whose year will be used to generate a two | |
216 * digit string representation of the year. | |
217 * | |
218 * @return A string that contains a 2 digit representation of the year. | |
219 * Single digits will be padded with 0. | |
220 * | |
221 * @langversion ActionScript 3.0 | |
222 * @playerversion Flash 9.0 | |
223 * @tiptext | |
224 */ | |
225 public static function getShortYear(d:Date):String | |
226 { | |
227 var dStr:String = String(d.getFullYear()); | |
228 | |
229 if(dStr.length < 3) | |
230 { | |
231 return dStr; | |
232 } | |
233 | |
234 return (dStr.substr(dStr.length - 2)); | |
235 } | |
236 | |
237 /** | |
238 * Compares two dates and returns an integer depending on their relationship. | |
239 * | |
240 * Returns -1 if d1 is greater than d2. | |
241 * Returns 1 if d2 is greater than d1. | |
242 * Returns 0 if both dates are equal. | |
243 * | |
244 * @param d1 The date that will be compared to the second date. | |
245 * @param d2 The date that will be compared to the first date. | |
246 * | |
247 * @return An int indicating how the two dates compare. | |
248 * | |
249 * @langversion ActionScript 3.0 | |
250 * @playerversion Flash 9.0 | |
251 * @tiptext | |
252 */ | |
253 public static function compareDates(d1:Date, d2:Date):int | |
254 { | |
255 var d1ms:Number = d1.getTime(); | |
256 var d2ms:Number = d2.getTime(); | |
257 | |
258 if(d1ms > d2ms) | |
259 { | |
260 return -1; | |
261 } | |
262 else if(d1ms < d2ms) | |
263 { | |
264 return 1; | |
265 } | |
266 else | |
267 { | |
268 return 0; | |
269 } | |
270 } | |
271 | |
272 /** | |
273 * Returns a short hour (0 - 12) represented by the specified date. | |
274 * | |
275 * If the hour is less than 12 (0 - 11 AM) then the hour will be returned. | |
276 * | |
277 * If the hour is greater than 12 (12 - 23 PM) then the hour minus 12 | |
278 * will be returned. | |
279 * | |
280 * @param d1 The Date from which to generate the short hour | |
281 * | |
282 * @return An int between 0 and 13 ( 1 - 12 ) representing the short hour. | |
283 * | |
284 * @langversion ActionScript 3.0 | |
285 * @playerversion Flash 9.0 | |
286 * @tiptext | |
287 */ | |
288 public static function getShortHour(d:Date):int | |
289 { | |
290 var h:int = d.hours; | |
291 | |
292 if(h == 0 || h == 12) | |
293 { | |
294 return 12; | |
295 } | |
296 else if(h > 12) | |
297 { | |
298 return h - 12; | |
299 } | |
300 else | |
301 { | |
302 return h; | |
303 } | |
304 } | |
305 | |
306 /** | |
307 * Returns a string indicating whether the date represents a time in the | |
308 * ante meridiem (AM) or post meridiem (PM). | |
309 * | |
310 * If the hour is less than 12 then "AM" will be returned. | |
311 * | |
312 * If the hour is greater than 12 then "PM" will be returned. | |
313 * | |
314 * @param d1 The Date from which to generate the 12 hour clock indicator. | |
315 * | |
316 * @return A String ("AM" or "PM") indicating which half of the day the | |
317 * hour represents. | |
318 * | |
319 * @langversion ActionScript 3.0 | |
320 * @playerversion Flash 9.0 | |
321 * @tiptext | |
322 */ | |
323 public static function getAMPM(d:Date):String | |
324 { | |
325 return (d.hours > 11)? "PM" : "AM"; | |
326 } | |
327 | |
328 /** | |
329 * Parses dates that conform to RFC822 into Date objects. This method also | |
330 * supports four-digit years (not supported in RFC822), but two-digit years | |
331 * (referring to the 20th century) are fine, too. | |
332 * | |
333 * This function is useful for parsing RSS .91, .92, and 2.0 dates. | |
334 * | |
335 * @param str | |
336 * | |
337 * @returns | |
338 * | |
339 * @langversion ActionScript 3.0 | |
340 * @playerversion Flash 9.0 | |
341 * @tiptext | |
342 * | |
343 * @see http://asg.web.cmu.edu/rfc/rfc822.html | |
344 */ | |
345 public static function parseRFC822(str:String):Date | |
346 { | |
347 var finalDate:Date; | |
348 try | |
349 { | |
350 var dateParts:Array = str.split(" "); | |
351 var day:String = null; | |
352 | |
353 if (dateParts[0].search(/\d/) == -1) | |
354 { | |
355 day = dateParts.shift().replace(/\W/, ""); | |
356 } | |
357 | |
358 var date:Number = Number(dateParts.shift()); | |
359 var month:Number = Number(DateUtil.getShortMonthIndex(dateParts.shift())); | |
360 var year:Number = Number(dateParts.shift()); | |
361 var timeParts:Array = dateParts.shift().split(":"); | |
362 var hour:Number = int(timeParts.shift()); | |
363 var minute:Number = int(timeParts.shift()); | |
364 var second:Number = (timeParts.length > 0) ? int(timeParts.shift()): 0; | |
365 | |
366 var milliseconds:Number = Date.UTC(year, month, date, hour, minute, second, 0); | |
367 | |
368 var timezone:String = dateParts.shift(); | |
369 var offset:Number = 0; | |
370 | |
371 if (timezone.search(/\d/) == -1) | |
372 { | |
373 switch(timezone) | |
374 { | |
375 case "UT": | |
376 offset = 0; | |
377 break; | |
378 case "UTC": | |
379 offset = 0; | |
380 break; | |
381 case "GMT": | |
382 offset = 0; | |
383 break; | |
384 case "EST": | |
385 offset = (-5 * 3600000); | |
386 break; | |
387 case "EDT": | |
388 offset = (-4 * 3600000); | |
389 break; | |
390 case "CST": | |
391 offset = (-6 * 3600000); | |
392 break; | |
393 case "CDT": | |
394 offset = (-5 * 3600000); | |
395 break; | |
396 case "MST": | |
397 offset = (-7 * 3600000); | |
398 break; | |
399 case "MDT": | |
400 offset = (-6 * 3600000); | |
401 break; | |
402 case "PST": | |
403 offset = (-8 * 3600000); | |
404 break; | |
405 case "PDT": | |
406 offset = (-7 * 3600000); | |
407 break; | |
408 case "Z": | |
409 offset = 0; | |
410 break; | |
411 case "A": | |
412 offset = (-1 * 3600000); | |
413 break; | |
414 case "M": | |
415 offset = (-12 * 3600000); | |
416 break; | |
417 case "N": | |
418 offset = (1 * 3600000); | |
419 break; | |
420 case "Y": | |
421 offset = (12 * 3600000); | |
422 break; | |
423 default: | |
424 offset = 0; | |
425 } | |
426 } | |
427 else | |
428 { | |
429 var multiplier:Number = 1; | |
430 var oHours:Number = 0; | |
431 var oMinutes:Number = 0; | |
432 if (timezone.length != 4) | |
433 { | |
434 if (timezone.charAt(0) == "-") | |
435 { | |
436 multiplier = -1; | |
437 } | |
438 timezone = timezone.substr(1, 4); | |
439 } | |
440 oHours = Number(timezone.substr(0, 2)); | |
441 oMinutes = Number(timezone.substr(2, 2)); | |
442 offset = (((oHours * 3600000) + (oMinutes * 60000)) * multiplier); | |
443 } | |
444 | |
445 finalDate = new Date(milliseconds - offset); | |
446 | |
447 if (finalDate.toString() == "Invalid Date") | |
448 { | |
449 throw new Error("This date does not conform to RFC822."); | |
450 } | |
451 } | |
452 catch (e:Error) | |
453 { | |
454 var eStr:String = "Unable to parse the string [" +str+ "] into a date. "; | |
455 eStr += "The internal error was: " + e.toString(); | |
456 throw new Error(eStr); | |
457 } | |
458 return finalDate; | |
459 } | |
460 | |
461 /** | |
462 * Returns a date string formatted according to RFC822. | |
463 * | |
464 * @param d | |
465 * | |
466 * @returns | |
467 * | |
468 * @langversion ActionScript 3.0 | |
469 * @playerversion Flash 9.0 | |
470 * @tiptext | |
471 * | |
472 * @see http://asg.web.cmu.edu/rfc/rfc822.html | |
473 */ | |
474 public static function toRFC822(d:Date):String | |
475 { | |
476 var date:Number = d.getUTCDate(); | |
477 var hours:Number = d.getUTCHours(); | |
478 var minutes:Number = d.getUTCMinutes(); | |
479 var seconds:Number = d.getUTCSeconds(); | |
480 var sb:String = new String(); | |
481 sb += DateBase.dayNamesShort[d.getUTCDay()]; | |
482 sb += ", "; | |
483 | |
484 if (date < 10) | |
485 { | |
486 sb += "0"; | |
487 } | |
488 sb += date; | |
489 sb += " "; | |
490 //sb += DateUtil.SHORT_MONTH[d.getUTCMonth()]; | |
491 sb += DateBase.monthNamesShort[d.getUTCMonth()]; | |
492 sb += " "; | |
493 sb += d.getUTCFullYear(); | |
494 sb += " "; | |
495 if (hours < 10) | |
496 { | |
497 sb += "0"; | |
498 } | |
499 sb += hours; | |
500 sb += ":"; | |
501 if (minutes < 10) | |
502 { | |
503 sb += "0"; | |
504 } | |
505 sb += minutes; | |
506 sb += ":"; | |
507 if (seconds < 10) | |
508 { | |
509 sb += "0"; | |
510 } | |
511 sb += seconds; | |
512 sb += " GMT"; | |
513 return sb; | |
514 } | |
515 | |
516 /** | |
517 * Parses dates that conform to the W3C Date-time Format into Date objects. | |
518 * | |
519 * This function is useful for parsing RSS 1.0 and Atom 1.0 dates. | |
520 * | |
521 * @param str | |
522 * | |
523 * @returns | |
524 * | |
525 * @langversion ActionScript 3.0 | |
526 * @playerversion Flash 9.0 | |
527 * @tiptext | |
528 * | |
529 * @see http://www.w3.org/TR/NOTE-datetime | |
530 */ | |
531 public static function parseW3CDTF(str:String):Date | |
532 { | |
533 var finalDate:Date; | |
534 try | |
535 { | |
536 var dateStr:String = str.substring(0, str.indexOf("T")); | |
537 var timeStr:String = str.substring(str.indexOf("T")+1, str.length); | |
538 var dateArr:Array = dateStr.split("-"); | |
539 var year:Number = Number(dateArr.shift()); | |
540 var month:Number = Number(dateArr.shift()); | |
541 var date:Number = Number(dateArr.shift()); | |
542 | |
543 var multiplier:Number; | |
544 var offsetHours:Number; | |
545 var offsetMinutes:Number; | |
546 var offsetStr:String; | |
547 | |
548 if (timeStr.indexOf("Z") != -1) | |
549 { | |
550 multiplier = 1; | |
551 offsetHours = 0; | |
552 offsetMinutes = 0; | |
553 timeStr = timeStr.replace("Z", ""); | |
554 } | |
555 else if (timeStr.indexOf("+") != -1) | |
556 { | |
557 multiplier = 1; | |
558 offsetStr = timeStr.substring(timeStr.indexOf("+")+1, timeStr.length); | |
559 offsetHours = Number(offsetStr.substring(0, offsetStr.indexOf(":"))); | |
560 offsetMinutes = Number(offsetStr.substring(offsetStr.indexOf(":")+1, offsetStr.length)); | |
561 timeStr = timeStr.substring(0, timeStr.indexOf("+")); | |
562 } | |
563 else // offset is - | |
564 { | |
565 multiplier = -1; | |
566 offsetStr = timeStr.substring(timeStr.indexOf("-")+1, timeStr.length); | |
567 offsetHours = Number(offsetStr.substring(0, offsetStr.indexOf(":"))); | |
568 offsetMinutes = Number(offsetStr.substring(offsetStr.indexOf(":")+1, offsetStr.length)); | |
569 timeStr = timeStr.substring(0, timeStr.indexOf("-")); | |
570 } | |
571 var timeArr:Array = timeStr.split(":"); | |
572 var hour:Number = Number(timeArr.shift()); | |
573 var minutes:Number = Number(timeArr.shift()); | |
574 var secondsArr:Array = (timeArr.length > 0) ? String(timeArr.shift()).split(".") : null; | |
575 var seconds:Number = (secondsArr != null && secondsArr.length > 0) ? Number(secondsArr.shift()) : 0; | |
576 //var milliseconds:Number = (secondsArr != null && secondsArr.length > 0) ? Number(secondsArr.shift()) : 0; | |
577 | |
578 var milliseconds:Number = (secondsArr != null && secondsArr.length > 0) ? 1000*parseFloat("0." + secondsArr.shift()) : 0; | |
579 var utc:Number = Date.UTC(year, month-1, date, hour, minutes, seconds, milliseconds); | |
580 var offset:Number = (((offsetHours * 3600000) + (offsetMinutes * 60000)) * multiplier); | |
581 finalDate = new Date(utc - offset); | |
582 | |
583 if (finalDate.toString() == "Invalid Date") | |
584 { | |
585 throw new Error("This date does not conform to W3CDTF."); | |
586 } | |
587 } | |
588 catch (e:Error) | |
589 { | |
590 var eStr:String = "Unable to parse the string [" +str+ "] into a date. "; | |
591 eStr += "The internal error was: " + e.toString(); | |
592 throw new Error(eStr); | |
593 } | |
594 return finalDate; | |
595 } | |
596 | |
597 /** | |
598 * Returns a date string formatted according to W3CDTF. | |
599 * | |
600 * @param d | |
601 * @param includeMilliseconds Determines whether to include the | |
602 * milliseconds value (if any) in the formatted string. | |
603 * | |
604 * @returns | |
605 * | |
606 * @langversion ActionScript 3.0 | |
607 * @playerversion Flash 9.0 | |
608 * @tiptext | |
609 * | |
610 * @see http://www.w3.org/TR/NOTE-datetime | |
611 */ | |
612 public static function toW3CDTF(d:Date,includeMilliseconds:Boolean=false):String | |
613 { | |
614 var date:Number = d.getUTCDate(); | |
615 var month:Number = d.getUTCMonth(); | |
616 var hours:Number = d.getUTCHours(); | |
617 var minutes:Number = d.getUTCMinutes(); | |
618 var seconds:Number = d.getUTCSeconds(); | |
619 var milliseconds:Number = d.getUTCMilliseconds(); | |
620 var sb:String = new String(); | |
621 | |
622 sb += d.getUTCFullYear(); | |
623 sb += "-"; | |
624 | |
625 //thanks to "dom" who sent in a fix for the line below | |
626 if (month + 1 < 10) | |
627 { | |
628 sb += "0"; | |
629 } | |
630 sb += month + 1; | |
631 sb += "-"; | |
632 if (date < 10) | |
633 { | |
634 sb += "0"; | |
635 } | |
636 sb += date; | |
637 sb += "T"; | |
638 if (hours < 10) | |
639 { | |
640 sb += "0"; | |
641 } | |
642 sb += hours; | |
643 sb += ":"; | |
644 if (minutes < 10) | |
645 { | |
646 sb += "0"; | |
647 } | |
648 sb += minutes; | |
649 sb += ":"; | |
650 if (seconds < 10) | |
651 { | |
652 sb += "0"; | |
653 } | |
654 sb += seconds; | |
655 if (includeMilliseconds && milliseconds > 0) | |
656 { | |
657 sb += "."; | |
658 sb += milliseconds; | |
659 } | |
660 sb += "-00:00"; | |
661 return sb; | |
662 } | |
663 | |
664 /** | |
665 * Converts a date into just after midnight. | |
666 */ | |
667 public static function makeMorning(d:Date):Date | |
668 { | |
669 var d:Date = new Date(d.time); | |
670 d.hours = 0; | |
671 d.minutes = 0; | |
672 d.seconds = 0; | |
673 d.milliseconds = 0; | |
674 return d; | |
675 } | |
676 | |
677 /** | |
678 * Converts a date into just befor midnight. | |
679 */ | |
680 public static function makeNight(d:Date):Date | |
681 { | |
682 var d:Date = new Date(d.time); | |
683 d.hours = 23; | |
684 d.minutes = 59; | |
685 d.seconds = 59; | |
686 d.milliseconds = 999; | |
687 return d; | |
688 } | |
689 | |
690 /** | |
691 * Sort of converts a date into UTC. | |
692 */ | |
693 public static function getUTCDate(d:Date):Date | |
694 { | |
695 var nd:Date = new Date(); | |
696 var offset:Number = d.getTimezoneOffset() * 60 * 1000; | |
697 nd.setTime(d.getTime() + offset); | |
698 return nd; | |
699 } | |
700 } | |
701 } |