{{ message }}
/ jruby Public

# File.mtime and friends return a date incorrect by an hour if created half a year ago#2404

Closed
opened this issue Jan 1, 2015 · 12 comments
Closed

# File.mtime and friends return a date incorrect by an hour if created half a year ago#2404

opened this issue Jan 1, 2015 · 12 comments
Labels
Milestone

### hakanai commented Jan 1, 2015

 This is a reopen of JRUBY-7064 after verifying that it still occurs on JRuby 1.7.18. The issue appears to be specific to Windows somehow, as noted by someone commenting on the original report. It also only occurs if you live in a region with daylight savings. Essentially, files created in a different zone offset from the current offset show the wrong time when File.mtime is used. Timestamps on files in NTFS are stored in UTC, so somewhere the wrong time zone is being applied here. To reproduce, first you must ensure that your time zone is set to one which uses daylight savings (we use Australia/Sydney, because that's where we are.) Create two files, one during daylight savings and one not. In my case, I just used "touch" to do this: Z:\Data\JRuby>touch -t "201208311416" "created during standard time.txt" Z:\Data\JRuby>touch -t "201212311416" "created during daylight time.txt"  Verify that the dates have been set correctly. You can verify this in Explorer. "dir" has an off by an hour bug as well, so you should avoid that. I used "ls" since I had it handy: -rw-rw-rw- 1 Tester 0 0 2012-12-31 14:16 created during daylight time.txt -rw-rw-rw- 1 Tester 0 0 2012-08-31 14:16 created during standard time.txt  When running JRuby's irb, you get the wrong time for one of the files (which one is wrong probably depends on the current date): Z:\Data\JRuby>java -jar z:\Data\jruby-complete-1.7.18.jar -S irb irb(main):001:0> puts File.mtime('created during standard time.txt') 2012-08-31 15:16:00 +1000 => nil irb(main):002:0> puts File.mtime('created during daylight time.txt') 2012-12-31 14:16:00 +1100 => nil  Notice how it somehow got the offset correct, even though it gets the actual date wrong... that's very weird. Usually you would expect it to get either both wrong or both right. This makes it particularly hard for a script to detect that this has occurred and compensate for it. (I'm not aware of a workaround, in fact.) MRI (2.0.0 used here, as it's what I happened to have on my Windows install) gets both right: C:\Data\JRuby>irb irb(main):001:0> RUBY_VERSION => "2.0.0" irb(main):002:0> File.mtime('created during standard time.txt') => 2012-08-31 14:16:00 +1000 irb(main):003:0> File.mtime('created during daylight time.txt') => 2012-12-31 14:16:00 +1100  This relatively simple Java program I whipped up to check if it was Java's fault also gets them right: import java.nio.file.Files; import java.nio.file.Paths; import java.time.ZoneId; public class FileTimesDemo { public static void main(String[] args) throws Exception { ZoneId zone = ZoneId.systemDefault(); System.out.println(Files.getLastModifiedTime(Paths.get("created during standard time.txt")).toInstant().atZone(zone)); System.out.println(Files.getLastModifiedTime(Paths.get("created during daylight time.txt")).toInstant().atZone(zone)); } }  Output of that: C:\Data\JRuby>java FileTimesDemo 2012-08-31T14:16+10:00[Australia/Sydney] 2012-12-31T14:16+11:00[Australia/Sydney]  The text was updated successfully, but these errors were encountered:

### hakanai commented Jan 1, 2015

 Narrowing down the issue, I wrote a test program only using the JNR POSIX stuff: import java.time.Instant; import java.time.ZoneId; import jnr.posix.FileStat; import jnr.posix.POSIX; import jnr.posix.POSIXFactory; import jnr.posix.util.DefaultPOSIXHandler; public class TestPosixFileTimes { public static void main(String[] args) throws Exception { printMTime("C:\\Users\\Daniel\\created during standard time.txt"); printMTime("C:\\Users\\Daniel\\created during daylight time.txt"); } private static void printMTime(String filePath) { // Gives the wrong result: POSIX posix = POSIXFactory.getPOSIX(); // Gives the right result: //POSIX posix = POSIXFactory.getJavaPOSIX(new DefaultPOSIXHandler()); FileStat stat = posix.stat(filePath); System.out.println("stat.mtime(): " + stat.mtime()); System.out.println(" => " + Instant.ofEpochSecond(stat.mtime()).atZone(ZoneId.systemDefault())); } }  Output confirms the wrong times: stat.mtime(): 1346390160 => 2012-08-31T15:16+10:00[Australia/Sydney] stat.mtime(): 1356923760 => 2012-12-31T14:16+11:00[Australia/Sydney]  Using the pure Java POSIX code, you get the right result: stat.mtime(): 1346386560 => 2012-08-31T14:16+10:00[Australia/Sydney] stat.mtime(): 1356923760 => 2012-12-31T14:16+11:00[Australia/Sydney] 

### headius commented Feb 24, 2015

 I was not able to reproduce this on JRuby 1.7 HEAD: C:\Users\headius\ruby (trunk) λ jruby -e "puts File.mtime('created during standard time.txt')" 2012-08-31 14:16:00 UTC C:\Users\headius\ruby (trunk) λ jruby -e "puts File.mtime('created during daylight time.txt')" 2012-12-31 14:16:00 UTC C:\Users\headius\ruby (trunk) λ jruby -v jruby 1.7.20-SNAPSHOT (1.9.3p551) 2015-02-24 258be73 on Java HotSpot(TM) 64-Bit Server VM 1.8.0_31-b13 +jit [Windows 7-amd64]  I am in US Central Time, which is a daylight savings zone. Does DST need to be active for this to fail?

### hakanai commented Feb 25, 2015

 That I'm not sure. I have a vague memory of verifying it in both directions, but here I have only reported the case of doing the test during DST. I can probably retest against the same version (and trunk) the next time I have access to the Windows computer.

### hakanai commented Feb 26, 2015

 1.7.18 when clock is set to May 1 (outside DST): C:\Users\Tester>java -jar z:\data\jruby-complete-1.7.18.jar -S irb irb(main):001:0> puts File.mtime('created during standard time.txt') 2012-08-31 14:16:00 +1000 => nil irb(main):002:0> puts File.mtime('created during daylight time.txt') 2012-12-31 13:16:00 +1100 => nil  So yep, both directions. Trying newer builds next.

### hakanai commented Feb 26, 2015

 Same on 1.7.19, except for an additional warning on the console: C:\Users\Tester>java -jar z:\data\jruby-complete-1.7.19.jar -S irb io/console not supported; tty will not be manipulated irb(main):001:0> puts File.mtime('created during standard time.txt') 2012-08-31 14:16:00 +1000 => nil irb(main):002:0> puts File.mtime('created during daylight time.txt') 2012-12-31 13:16:00 +1100 => nil irb(main):003:0>  9.0.0.0.pre1 fails to start altogether: C:\Users\Tester>java -jar z:\data\jruby-complete-9.0.0.0.pre1.jar -S irb Errno::EPIPE: Broken pipe - uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb/lc/error.rb rewind at org/jruby/RubyIO.java:1726 open at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb/magic-file.rb:13 real_load at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb/locale.rb:129 load at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb/locale.rb:109 init_error at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb/init.rb:120 setup at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb/init.rb:17 start at uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/irb.rb:378 (root) at uri:classloader:/META-INF/jruby.home/bin/jirb:13 load at org/jruby/RubyKernel.java:969 (root) at file:/Z:/Data/jruby-complete-9.0.0.0.pre1.jar!/jruby/commands.rb:1 __script__ at jirb:1 

### hakanai commented Apr 28, 2017

 Witnessed on 9.0.5.0 as well. Granted, that version is out of date.

### enebo commented May 16, 2017

 @trejkaz can you try 9.1.9.0 for us?

### hakanai commented May 17, 2017

 Pushing an attempted update into the pipeline to see. Unfortunately I don't have a quick way to run automated tests on Windows and I don't use Windows myself either. When we tried updating to 9.1.6.0, supposedly some clash against Jython caused things to fail, but I'm not sure that was the case so I'm trying anyway. If only travis-ci would add Windows support, I could make a little test project and put the test in it :/

### enebo commented May 17, 2017

 @trejkaz you can use appveyor for windows CI and it is free for OSS stuff.

### hakanai commented May 18, 2017

 appveyor looks doable actually. Though that's Windows-only, and I would have preferred to run everything on one CI to get the results in one place. :( Anyway, the overnight run appears to have worked correctly. I get no skew for either of the two files being tested. Hopefully we don't get blocked for updating it by other libraries... (Jython is the most likely trouble-maker because they have a poor policy for keeping their dependencies up to date.)

### hakanai commented May 18, 2017 • edited

 Ah, I get a new failure in some other File-related test. @Test public void testResolveClasspath() throws Exception { ScriptEngine engine = createEngine(); String path = "classpath:/path/to/this/TestRubyFile.class"; String result = (String) engine.eval("File.realpath('" + path + "')"); assertThat(result, is(equalTo(path))); }  This, too, works on my box when I run it, so it must be another Windows-specific thing. Failure is: Errno::ENOENT: No such file or directory - classpath:BY\path\to\this\TestRubyFile.class  File another ticket, I guess, and keep waiting? :/

### hakanai commented May 30, 2017

 9.1.10.0 update fixed the latter issue I got, and my File test still passes, so let's call it done.

closed this as completed May 30, 2017
added this to the JRuby 9.1.9.0 milestone May 30, 2017