0

Java application writes events to a log file, including a timestamp (as returned from Date.toString()), which in turn includes the time zone. On the Windows machines I use, I see the string returned by Date.toString() having the time zone represented as a three-character string (e.g. "CST"). But on some customer machines, the dates are being written to the log file with the time zone represented as an offset from GMT (e.g. "GMT-06:00").

We have a tool that parses the text of log files for various pieces of information, but unfortunately, its original implementation assumed the three-character representation and won't work on those log files that have the GMT-offset representation. We've fixed the tool to be indifferent to that now, but we'd like to be able to advise customers who are running an old version and are having this problem due to their strings having GMT-offset time zones, that they can get the tool to start working if they change their system settings so that their logs files are written with three-character string time zone strings going forward. Additionally, we'd like to account for this variability in our future test plans, ensuring that we test things using each setting. But I haven't been able to determine just what in Windows setting tells Java to use "CST" vs. use "GMT-06:00".

I see a couple of time-zone related registry settings, but nothing that I can clearly identify as controlling that particular choice. Some of the registry settings refer to tzres.dll. Is the choice baked into that? Is there any simple way on Windows to get Date.toString() to formulate its string using one time zone representation vs. using the other?

Michael
  • 325
  • 1
  • 3
  • 9
  • exactly how is this log file written? Is the date string being generated in that code? So show that code... – Marc B May 05 '14 at 05:29
  • String timestamp = new Date(System.currentTimeMillis()).toString(); – Michael May 06 '14 at 07:13
  • @Michael You should edit your question with crucial information such as this, rather than post a comment, as long as you are not changing the nature of the question. Notice the "edit" link to the lower left of your Question. – Basil Bourque May 07 '14 at 08:22
  • Actually, my original question already says and always has said quite explicitly that the timestamp string comes from Date.toString(). – Michael May 08 '14 at 09:18

1 Answers1

0

I don't know the exact cause of this difference in behavior, but I can guess. A time zone is an offset from UTC and history & info about anomalies for that particular are such as Daylight Saving Time. Some machines (or the JVM default) may be set to only an offset rather than a specific named time zone.

The java.util.Date class is notoriously troublesome in general, and should be avoided. Specifically, the toString is terrible in two ways. (A) The format it uses to generate the string is bad, as you have discovered. (B) the JVM's default time zone is applied. That application causes confusion as it implies a Date has a time zone when in fact it does not. This method should only be used temporarily for quick-and-dirty purposes, never for logging.

Use a decent date-time library. That means either Joda-Time or the new java.time package in Java 8. Both use the sensible and useful ISO 8601 format by default.

Generally best practice is to do your logging in UTC time zone (no offset).

Example: 2014-05-04T10:36:34Z

To generate such a value in Joda-Time:

String output = new DateTime( DateTimeZone.UTC ).toString();

If your question is, "How do I change the time zone used by a JVM running an app I cannot alter?", one solution is setting the JVM's time zone by passing an argument when launching the JVM. See this question.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thanks. Indeed we will be making a Java 8 move and looking to avert similar problems in the future. But there's still the matter of the existing tool being the way it is and trying to find an effective workaround for customers who have that version. – Michael May 06 '14 at 07:27
  • I suppose I was trying to say that you are in a pickle if stuck with bad code that relies on java.util.Date's `toString` method. One hack might be programmatically setting the JVM's default time zone to UTC, thereby overriding the default to host machine's time zone. But be aware setting the JVM's time zone affects all code running in that JVM. – Basil Bourque May 06 '14 at 07:34
  • Also, you may be able to parse both styles of format you are seeing by using Joda-Time. Search StackOverflow for many examples. – Basil Bourque May 06 '14 at 07:37
  • Gotcha. With regard to changing *our* stuff going forward, we're good. What would have been valuable on top of that would be something that a customer could do easily to change *their* system (e.g. Registry setting/Control Panel setting/etc.) that would cause our out-in-the-field-already version to play nicely. But sounds like we're going to be out of luck there. – Michael May 07 '14 at 06:00
  • @Michael You could have your customer pass an argument to the JVM running the app you do not control, to set the time zone. See link in last part of my updated answer. – Basil Bourque May 07 '14 at 08:19
  • You know when I first read that I didn't think it would work because I was thinking the longer offset version would still print. But, of course, if it's UTC, then of course, there would be no offset and it should end go to a three-letter version only. Brain freeze that I didn't catch that before. Thanks, I'll suggest that. – Michael May 08 '14 at 09:20