1 37 package org.jruby; 38 39 import java.text.SimpleDateFormat ; 40 import java.util.Calendar ; 41 import java.util.Date ; 42 import java.util.Locale ; 43 import java.util.Map ; 44 import java.util.TimeZone ; 45 46 import org.jruby.runtime.Block; 47 import org.jruby.runtime.builtin.IRubyObject; 48 import org.jruby.util.RubyDateFormat; 49 import org.jruby.util.ByteList; 50 51 55 public class RubyTime extends RubyObject { 56 public static final String UTC = "UTC"; 57 private Calendar cal; 58 private long usec; 59 60 private static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat ("-", Locale.US); 61 62 public static TimeZone getLocalTimeZone(Ruby runtime) { 63 RubyString tzVar = runtime.newString("TZ"); 65 Map h = ((RubyHash)runtime.getObject().getConstant("ENV")).getValueMap(); 66 IRubyObject tz = (IRubyObject)h.get(tzVar); 67 if (tz == null || ! (tz instanceof RubyString)) { 68 return TimeZone.getDefault(); 69 } else { 70 return TimeZone.getTimeZone(tz.toString()); 71 } 72 } 73 74 public RubyTime(Ruby runtime, RubyClass rubyClass) { 75 super(runtime, rubyClass); 76 } 77 78 public RubyTime(Ruby runtime, RubyClass rubyClass, Calendar cal) { 79 super(runtime, rubyClass); 80 this.cal = cal; 81 } 82 83 public void setUSec(long usec) { 84 this.usec = usec; 85 } 86 87 public void updateCal(Calendar calendar) { 88 calendar.setTimeZone(cal.getTimeZone()); 89 calendar.setTimeInMillis(getTimeInMillis()); 90 } 91 92 protected long getTimeInMillis() { 93 return cal.getTimeInMillis(); } 95 96 public static RubyTime newTime(Ruby runtime, long milliseconds) { 97 Calendar cal = Calendar.getInstance(); 98 RubyTime time = new RubyTime(runtime, runtime.getClass("Time"), cal); 99 100 cal.setTimeInMillis(milliseconds); 101 102 return time; 103 } 104 105 public static RubyTime newTime(Ruby runtime, Calendar cal) { 106 RubyTime time = new RubyTime(runtime, runtime.getClass("Time"), cal); 107 108 return time; 109 } 110 111 public IRubyObject initialize_copy(IRubyObject original) { 112 if (!(original instanceof RubyTime)) { 113 throw getRuntime().newTypeError("Expecting an instance of class Time"); 114 } 115 116 RubyTime originalTime = (RubyTime) original; 117 118 cal = originalTime.cal; 119 usec = originalTime.usec; 120 121 return this; 122 } 123 124 public RubyTime succ() { 125 Calendar newCal = (Calendar )cal.clone(); 126 newCal.add(Calendar.SECOND,1); 127 return newTime(getRuntime(),newCal); 128 } 129 130 public RubyTime gmtime() { 131 cal.setTimeZone(TimeZone.getTimeZone(UTC)); 132 return this; 133 } 134 135 public RubyTime localtime() { 136 long dump = cal.getTimeInMillis(); 137 cal = Calendar.getInstance(getLocalTimeZone(getRuntime())); 138 cal.setTimeInMillis(dump); 139 return this; 140 } 141 142 public RubyBoolean gmt() { 143 return getRuntime().newBoolean(cal.getTimeZone().getID().equals(UTC)); 144 } 145 146 public RubyTime getgm() { 147 Calendar newCal = (Calendar )cal.clone(); 148 newCal.setTimeZone(TimeZone.getTimeZone(UTC)); 149 return newTime(getRuntime(), newCal); 150 } 151 152 public RubyTime getlocal() { 153 Calendar newCal = (Calendar )cal.clone(); 154 newCal.setTimeZone(getLocalTimeZone(getRuntime())); 155 return newTime(getRuntime(), newCal); 156 } 157 158 public RubyString strftime(IRubyObject format) { 159 final RubyDateFormat rubyDateFormat = new RubyDateFormat("-", Locale.US); 160 rubyDateFormat.setCalendar(cal); 161 rubyDateFormat.applyPattern(format.toString()); 162 String result = rubyDateFormat.format(cal.getTime()); 163 164 return getRuntime().newString(result); 165 } 166 167 public IRubyObject op_ge(IRubyObject other) { 168 if (other instanceof RubyTime) { 169 return getRuntime().newBoolean(cmp((RubyTime) other) >= 0); 170 } 171 172 return RubyComparable.op_ge(this, other); 173 } 174 175 public IRubyObject op_gt(IRubyObject other) { 176 if (other instanceof RubyTime) { 177 return getRuntime().newBoolean(cmp((RubyTime) other) > 0); 178 } 179 180 return RubyComparable.op_gt(this, other); 181 } 182 183 public IRubyObject op_le(IRubyObject other) { 184 if (other instanceof RubyTime) { 185 return getRuntime().newBoolean(cmp((RubyTime) other) <= 0); 186 } 187 188 return RubyComparable.op_le(this, other); 189 } 190 191 public IRubyObject op_lt(IRubyObject other) { 192 if (other instanceof RubyTime) { 193 return getRuntime().newBoolean(cmp((RubyTime) other) < 0); 194 } 195 196 return RubyComparable.op_lt(this, other); 197 } 198 199 private int cmp(RubyTime other) { 200 long millis = getTimeInMillis(); 201 long millis_other = other.getTimeInMillis(); 202 long usec_other = other.usec; 203 204 if (millis > millis_other || (millis == millis_other && usec > usec_other)) { 205 return 1; 206 } else if (millis < millis_other || (millis == millis_other && usec < usec_other)) { 207 return -1; 208 } 209 210 return 0; 211 } 212 213 public IRubyObject op_plus(IRubyObject other) { 214 long time = getTimeInMillis(); 215 216 if (other instanceof RubyTime) { 217 throw getRuntime().newTypeError("time + time ?"); 218 } 219 time += ((RubyNumeric) other).getDoubleValue() * 1000; 220 221 RubyTime newTime = new RubyTime(getRuntime(), getMetaClass()); 222 newTime.cal = Calendar.getInstance(); 223 newTime.cal.setTimeZone(cal.getTimeZone()); 224 newTime.cal.setTime(new Date (time)); 225 226 return newTime; 227 } 228 229 public IRubyObject op_minus(IRubyObject other) { 230 long time = getTimeInMillis(); 231 232 if (other instanceof RubyTime) { 233 time -= ((RubyTime) other).getTimeInMillis(); 234 235 return RubyFloat.newFloat(getRuntime(), time * 10e-4); 236 } 237 time -= ((RubyNumeric) other).getDoubleValue() * 1000; 238 239 RubyTime newTime = new RubyTime(getRuntime(), getMetaClass()); 240 newTime.cal = Calendar.getInstance(); 241 newTime.cal.setTimeZone(cal.getTimeZone()); 242 newTime.cal.setTime(new Date (time)); 243 244 return newTime; 245 } 246 247 public IRubyObject same2(IRubyObject other) { 248 return (RubyNumeric.fix2int(callMethod(getRuntime().getCurrentContext(), "<=>", other)) == 0) ? getRuntime().getTrue() : getRuntime().getFalse(); 249 } 250 251 public IRubyObject op_cmp(IRubyObject other) { 252 if (other.isNil()) { 253 return other; 254 } 255 256 if (other instanceof RubyTime) { 257 return getRuntime().newFixnum(cmp((RubyTime) other)); 258 } 259 260 long millis = getTimeInMillis(); 261 262 if(other instanceof RubyNumeric) { 263 if (other instanceof RubyFloat || other instanceof RubyBignum) { 264 double time = millis / 1000.0; 265 266 double time_other = ((RubyNumeric) other).getDoubleValue(); 267 268 if (time > time_other) { 269 return RubyFixnum.one(getRuntime()); 270 } else if (time < time_other) { 271 return RubyFixnum.minus_one(getRuntime()); 272 } 273 274 return RubyFixnum.zero(getRuntime()); 275 } 276 long millis_other = RubyNumeric.num2long(other) * 1000; 277 278 if (millis > millis_other || (millis == millis_other && usec > 0)) { 279 return RubyFixnum.one(getRuntime()); 280 } else if (millis < millis_other || (millis == millis_other && usec < 0)) { 281 return RubyFixnum.minus_one(getRuntime()); 282 } 283 284 return RubyFixnum.zero(getRuntime()); 285 } 286 return getRuntime().getNil(); 287 } 288 289 public RubyString asctime() { 290 simpleDateFormat.setCalendar(cal); 291 simpleDateFormat.applyPattern("EEE MMM dd HH:mm:ss yyyy"); 292 String result = simpleDateFormat.format(cal.getTime()); 293 294 return getRuntime().newString(result); 295 } 296 297 public IRubyObject to_s() { 298 simpleDateFormat.setCalendar(cal); 299 simpleDateFormat.applyPattern("EEE MMM dd HH:mm:ss z yyyy"); 300 String result = simpleDateFormat.format(cal.getTime()); 301 302 return getRuntime().newString(result); 303 } 304 305 public RubyArray to_a() { 306 return getRuntime().newArrayNoCopy(new IRubyObject[] { sec(), min(), hour(), mday(), month(), 307 year(), wday(), yday(), isdst(), zone() }); 308 } 309 310 public RubyFloat to_f() { 311 return RubyFloat.newFloat(getRuntime(), getTimeInMillis() / 1000 + microseconds() / 1000000.0); 312 } 313 314 public RubyInteger to_i() { 315 return getRuntime().newFixnum(getTimeInMillis() / 1000); 316 } 317 318 public RubyInteger usec() { 319 return getRuntime().newFixnum(microseconds()); 320 } 321 322 public void setMicroseconds(long mic) { 323 long millis = getTimeInMillis() % 1000; 324 long withoutMillis = getTimeInMillis() - millis; 325 withoutMillis += (mic / 1000); 326 cal.setTimeInMillis(withoutMillis); 327 usec = mic % 1000; 328 } 329 330 public long microseconds() { 331 return getTimeInMillis() % 1000 * 1000 + usec; 332 } 333 334 public RubyInteger sec() { 335 return getRuntime().newFixnum(cal.get(Calendar.SECOND)); 336 } 337 338 public RubyInteger min() { 339 return getRuntime().newFixnum(cal.get(Calendar.MINUTE)); 340 } 341 342 public RubyInteger hour() { 343 return getRuntime().newFixnum(cal.get(Calendar.HOUR_OF_DAY)); 344 } 345 346 public RubyInteger mday() { 347 return getRuntime().newFixnum(cal.get(Calendar.DAY_OF_MONTH)); 348 } 349 350 public RubyInteger month() { 351 return getRuntime().newFixnum(cal.get(Calendar.MONTH) + 1); 352 } 353 354 public RubyInteger year() { 355 return getRuntime().newFixnum(cal.get(Calendar.YEAR)); 356 } 357 358 public RubyInteger wday() { 359 return getRuntime().newFixnum(cal.get(Calendar.DAY_OF_WEEK) - 1); 360 } 361 362 public RubyInteger yday() { 363 return getRuntime().newFixnum(cal.get(Calendar.DAY_OF_YEAR)); 364 } 365 366 public RubyInteger gmt_offset() { 367 return getRuntime().newFixnum((int)(cal.get(Calendar.ZONE_OFFSET)/1000)); 368 } 369 370 public RubyBoolean isdst() { 371 return getRuntime().newBoolean(cal.getTimeZone().inDaylightTime(cal.getTime())); 372 } 373 374 public RubyString zone() { 375 return getRuntime().newString(cal.getTimeZone().getID()); 376 } 377 378 public void setJavaCalendar(Calendar cal) { 379 this.cal = cal; 380 } 381 382 public Date getJavaDate() { 383 return this.cal.getTime(); 384 } 385 386 public RubyFixnum hash() { 387 return getRuntime().newFixnum((int)(((cal.getTimeInMillis() / 1000) ^ microseconds()) << 1) >> 1); 389 } 390 391 public RubyString dump(final IRubyObject[] args, Block unusedBlock) { 392 if (args.length > 1) { 393 throw getRuntime().newArgumentError(0, 1); 394 } 395 396 return (RubyString) mdump(new IRubyObject[] { this }); 397 } 398 399 public RubyObject mdump(final IRubyObject[] args) { 400 RubyTime obj = (RubyTime)args[0]; 401 Calendar calendar = obj.gmtime().cal; 402 byte dumpValue[] = new byte[8]; 403 int pe = 404 0x1 << 31 | 405 (calendar.get(Calendar.YEAR)-1900) << 14 | 406 calendar.get(Calendar.MONTH) << 10 | 407 calendar.get(Calendar.DAY_OF_MONTH) << 5 | 408 calendar.get(Calendar.HOUR_OF_DAY); 409 int se = 410 calendar.get(Calendar.MINUTE) << 26 | 411 calendar.get(Calendar.SECOND) << 20 | 412 calendar.get(Calendar.MILLISECOND); 413 414 for(int i = 0; i < 4; i++) { 415 dumpValue[i] = (byte)(pe & 0xFF); 416 pe >>>= 8; 417 } 418 for(int i = 4; i < 8 ;i++) { 419 dumpValue[i] = (byte)(se & 0xFF); 420 se >>>= 8; 421 } 422 return RubyString.newString(obj.getRuntime(), new ByteList(dumpValue,false)); 423 } 424 } 425 | Popular Tags |