1

As response from .net service I get this date format: /Date(1233323754523+0100)/

1233323754523 is date in timestamp format, but I don't know what +0100 mean and how to generate this from java code?

Thanks

Jovan
  • 4,684
  • 13
  • 64
  • 98
  • 4
    I strongly suspect that the +0100 is an offset of one hour from UTC, for the time zone. – Jon Skeet Sep 28 '11 at 21:29
  • UTC offset does indeed make the most sense. – Barend Sep 28 '11 at 21:33
  • thanks I wonder if this is necessary? Whether the result will be the same without it- while serializing and deserializing – Jovan Sep 28 '11 at 21:41
  • You really do need the timezone offset if the stuff gets sent to machines with different timezone settings. If all the computers using this are in the same time zone, you'd get away with ignoring it, but that would pretty much mean the code is accidentally working correctly. – Barend Sep 28 '11 at 21:57
  • 1
    If 1233323754523 is milliseconds since 1970, that would be 2009-01-30 13:55:54 UTC; is that what you expect it to be? Combining a time zone with a Unix-style timestamp seems like a very bad idea to me; Unix-style timestamps are inherently UTC. The best approach is to store times as UTC, and then apply the local time zone offset on top of that for display. Maybe .net does it differently? – Keith Thompson Sep 28 '11 at 22:23

3 Answers3

3

I assume that the timestamp is in UTC and the offset is the UTC offset of the desired local time. If the timestamp is in the given offset from UTC, you'd have to generate it slightly differently.

A reliable way to generate this in Java would be using the Joda-Time library, which is much better than de default java.util.Date and java.util.Calendar classes.

// A formatter that prints the timezone offset
DateTimeFormatter fmt = DateTimeFormat.forPattern("Z");

// The current date+time in the system default timezone.
DateTime dt = new DateTime();

// Create the result.
String result = "/Date(" + dt.getMillis() + fmt.print(dt) + ")/";

It's a bit unfortunate that the DateTimeFormat does not have a way to output the milliseconds since epoch; that's what necessitates the dt.getMillis() string concatenation.

To generate the same thing using the java.util classes would look something like this:

// A formatter that prints the timezone offset
SimpleDateFormat df = new SimpleDateFormat("Z");    

// Current date+time in system default timezone.
Calendar now = Calendar.getInstance();

// Don't forget this if you use a timezone other than system default:
df.setTimeZone( now.getTimeZone() );

// Create the result
String result = "/Date(" now.getTimeInMillis() + df.format(now.getTime()) +")/";

It's essentially the same as the Joda-Time example, but the bit where you have to copy the time zone from the calendar into the date formatter is a major source of bugs.

Barend
  • 17,296
  • 2
  • 61
  • 80
2

The question is a little out of date, but i think there's still some people out there hitting their heads against a wall because of that excellent date time format choice ;)

Serialisation and deserialisation type adapter of a .NET Json formatted DateTime value in Java for Gson This worked for me now since around 2years.

package x

import java.lang.reflect.Type;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.regex.Pattern;

import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

/**
 * Serialises and deserialises a string representing a date produced by a .NET web service.
 * 
 * @author Diego Frehner
 */
public class TypeAdapterDate implements JsonSerializer<Date>, JsonDeserializer<Date> {

  /** Pattern for parsing date time values sent by a .NET web service. */
  private static Pattern pattern = Pattern.compile("^/Date\\([0-9\\+-]*\\)/$");

  private static DecimalFormat formatter = new DecimalFormat("#00.###");

  private static final long HOUR_IN_MILLISECOND = 60L * 60 * 1000;

  private static final String minusSign = "-";

  private static final String plusSign = "+";

  @Override
  public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext     context) throws JsonParseException {
    String value = json.getAsString();
    // example .NET web service return value: /Date(1302847200000+0200)/
    // milliseconds since midnight 1970 UTC + time zone offset of the server to UTC
    // GMT == UTC == UT it's all the same...afaik
    if (!pattern.matcher(value).matches()) {
      return null;
    }
    // get UTC millisecond value
    long utcMillisecond = Long.parseLong(value.substring(value.indexOf("(") + 1, value.indexOf(")") - 5));

    // new Date(long) takes milliseconds since 1970 in UTC
    return new Date(utcMillisecond);
  }

  @Override
  public JsonElement serialize(Date arg0, Type arg1, JsonSerializationContext arg2) {
    Date date = (Date) arg0;

    int zoneOffsetMillisecond = TimeZone.getDefault().getOffset(date.getTime());
    String sign = plusSign;
    if (zoneOffsetMillisecond < 0) { // negative offset
      sign = minusSign;
      zoneOffsetMillisecond *= -1;
    }
    int minute = (int) (zoneOffsetMillisecond % HOUR_IN_MILLISECOND);
    int hour = (zoneOffsetMillisecond / 1000 / 60 / 60);
    return new JsonPrimitive("/Date(" + date.getTime() + sign + formatter.format(hour) + formatter.format(minute) + ")/");
  }
}
Diego Frehner
  • 2,396
  • 1
  • 28
  • 35
2

The second number simply indicates that the DateTime value should be interpreted as a local date time (instead of UTC), the number itself is ignored. This is described in the Advanced Information / DateTime wire format section of the document at http://msdn.microsoft.com/en-us/library/bb412170.aspx.

carlosfigueira
  • 85,035
  • 14
  • 131
  • 171