java Date problem

B

Big Jim

Cheers Paul,

I understand the conversion but confused about where they are
performed. Considering I can only send longs between client and server,
the server has no timezone info about the client, the server could also
be in any timezone and it has to be stored in the DB as a date, are you
suggesting (for a "round trip"):

1.the user entry is converted to a long using d.getTime and sent to the
server
2.the server uses sdfGMTLots to convert to a date and stores this in
the DB
3.the server gets the date from the DB and converts to a long somehow
4.the client uses sdfLocalLots to convert the long and display the date

Step 3 I'm not sure about, if the date in the DB is GMT and the server
could be anywhere, how would it generate the correct long to be sent to
clients?

Cheers, Richard.
 
N

Nigel Wade

Big said:
but when a user in Tokyo types in 6th March 2006 (defaulting to midnight),
and in his client that gets converted to seconds from the epoch (to send it
to the server), when the server converts this long to a date it'll get 5th
March

But that is what the time was at the server when the user entered "6th March" in
Tokyo. I don't see what your problem is.
because (and this is my point):

midnight on 6th March in Tokyo is a different number of seconds from the
epoch than midnight 6th March in London.

Yes.

A number of seconds since the epoch represents a distinct instant in time. If
that is recorded in the server, the location, timezone (whatever) of the server
and client is irrelevant. The server can supply that instant in time to any
client, anywhere in the world, and the client can convert it to local time to
display to the user.
Hence the client needs to convert to GMT before sending the long hence the
correction.

and that's exactly what Date.getTime(), Calendar.getTimeInMillis() already do
for you. The time they return is in UTC.

The server has no idea what timezone the client was in so it
can't do this conversion.

e.g if you do:

new java.util.Date(61081516800000L)
new java.util.Date(61092403200000L)
in London you'll get: Aug 7th 1am Dec 11th midnight
in Tokyo you'll get: Aug 7th 9am Dec 11th 9am

So then the server then needs to convert this long to a date, new
Date(long), to store it in the DB and again it has to take account of where
it is (as java takes the timezone into account when it does this conversion
and I want to make sure the DB val is the date/time the user typed in but in
GMT) and it also has to take into account whether the date it's converting
has had daylight savings applied - as can be seen in the example that also
changes the difference.

No you don't need to take any of that into account at all. If the user enters a
date in local time (with DST) then you convert to epoch simply by
getTimeInMillis() and send that to the server. At the server you *have* to have
a convention which is rigidly adhered to. It's best to store the epoch time in
seconds or milliseconds. But if you absolutely have to store a "date" then you
it's meaningless without a timezone to give it reference. You can do this
implicitly by specifying that the date recorded is GMT/UT/whatever. If you do
that you have to ensure that all date/time calculations in the server code take
place in that fixed timezone, not the timezone of the server. You do that, for
example, by fixing the timezone in the Calendar object with:

calendarObject.setTimeZone(TimeZone.getTimeZone("GMT"))

so there is no timezone/DST to worry about internally within the server code.
Your server can be running with it's timezone set to GMT, BST or Outer
Mongolian time, and all the dates recorded in the database will be in GMT.
 
O

Oliver Wong

Big Jim said:
Cheers Paul,

I understand the conversion but confused about where they are
performed. Considering I can only send longs between client and server,
the server has no timezone info about the client, the server could also
be in any timezone and it has to be stored in the DB as a date, are you
suggesting (for a "round trip"):

1.the user entry is converted to a long using d.getTime and sent to the
server
2.the server uses sdfGMTLots to convert to a date and stores this in
the DB
3.the server gets the date from the DB and converts to a long somehow
4.the client uses sdfLocalLots to convert the long and display the date

Step 3 I'm not sure about, if the date in the DB is GMT and the server
could be anywhere, how would it generate the correct long to be sent to
clients?

In step 3, the server will send the same long it received in step 1. So
whatever the client sent, that's exactly the time he'll get back. To give a
concrete example:

1. User is in EST, without DST, so essentially the user is in GMT-4. Local
time for that user is 9:17 AM, April 4th, 2006. The timestamp for that is
1144156309. User sends "1144156309".

2. Server receives "1144156309". Server is in GMT+4, so 1144156309 seconds
from the epoch represents the point known as 5:17 PM, April 4th, 2006. Note
that this represents the same point in time as what the client is referring
to, but the "toString representation" differs because the two machines are
in different time zones.

3. Server gets the date from the DB, "5:17 PM, April 4th, 2006" and converts
this to a unix timestamp. That yields 1144156309. Server sends that to the
client.

4. Client receives "1144156309", converts that to a local date. Thus user
ends up with "9:17 AM, April 4th, 2006", which is what the user had
originally sent in the first place.

Note that no adding or subtracting has occured on the timestamp itself.

- Oliver
 
P

P.Hill

Big said:
Cheers guys, think I'm sorted now.

All the best.


I hope so, because my solution did NOT require the use of the sdfLots on
the server. The sdfLots was only used to peek inside the date object
and see what datetime it had including the hh:mmm:ss. It is never part
of the solution flow.

My solution was to treat the input as a date in UTC and pass that around.

What this really is a substitute for a datatype that you sometimes see
in other type collections, a datetime without NO timezone, not UTC.

The following statement contains such a no timezone datetime.
"All of Employees of Acme Corporation are welcome to go home
and party in remembrance of birthday of our founder at 5:00 PM on
Friday."

The following statement contains a GMT time:
"All managers in the FooBar project should be on the conference
call at 8 PM GMT."

The first is a set of that look the same as local times.

-Paul
 
S

steve

Cheers Steve, that sounds like the best plan.

Unfortunately this is an urgent fix to let "deals" be entered globally and
the extra info passing would require changing IDL etc. so I'm stuck with the
client conversion to long mess for now. Next proper release I think I'll
take your suggestion.

Ahh, well , you did not say it was an urgent "bug" fix!! ;-)

the only other solution is to make a callout to a time server , from the
client.

Steve
 
S

steve

If you get them to use SetClock or similar, at least you can for the
most part avoid that problem. See
http://mindprod.com/webstarts/setclock.html

rodders, These are users!! .

You are dealing with- people that:

1. Actually believe that clicking the "remove" on a spam email , removes your
details.
2. Think that a non working computer is the fault of your application , when
a fuse blows and the screen goes dead.
3. Set the GMT+ & keyboard layout , to where they would like to be ,or come
from, rather than where they actually are.
4. join your company stating they are fluent in Word/excel/outlook express,
and cannot even set the page orientation for said apps.
5. Think it is your job to answer every little query they have about above
apps, and get upset when you recommend they use the "Help" function, besides
it is faster & less work for THEM to disrupt your productive work flow.
6. Think that just because a program SAYS it is safe to download & install
from the net, it must be true.


Steve
 
S

steve

Big said:
Cheers Steve, that sounds like the best plan.

Unfortunately this is an urgent fix to let "deals" be entered globally and
the extra info passing would require changing IDL etc. so I'm stuck with
the
client conversion to long mess for now. Next proper release I think I'll
take your suggestion.

As Oliver suggested, please, get rid of the hand calculation subtracting
off the local offset. As he says, this contains a bug.

Do what you stated the problem is:
"The users [types] in dates "mm/dd/yyyy" for a "deal" object and these
get translated to a long, [...]
I want to store the dates as midnight GMT in the DB (datetime col).
simple, the API does do that (really it does)"

Okay, let's try.

String userInput = "04/03/06";

String FORMAT_INPUT = "dd/MM/yy";
String FORMAT_EVERYTHING = "dd/MM/yy HH:mm.ss zzz (ZZZ)";

SimpleDateFormat sdfGMT = new SimpleDateFormat(FORMAT_INPUT);
sdfGMT.setTimeZone(TimeZone.getTimeZone("GMT"));

SimpleDateFormat sdfGMTLots = new SimpleDateFormat(FORMAT_EVERYTHING);
sdfGMTLots.setTimeZone(TimeZone.getTimeZone("GMT"));

SimpleDateFormat sdfLocalLots = new SimpleDateFormat(FORMAT_EVERYTHING);

Date d = sdfGMT.parse(userInput);

System.out.println( "Let's see what is in the Date as GMT: " +
sdfGMTLots.format(d));
System.out.println( "Let's see what is in the Date in local time: " +
sdfLocalLots.format(d));

System.out.println( "As a long it is : " + d.getTime());

Results in:
Let's see what is in the Date as GMT: 04/03/06 00:00.00 GMT (+0000)
Let's see what is in the Date in local time: 03/03/06 16:00.00 PST (-0800)
As a long it is : 1141430400000

No hand calculations required, no setting of calendars, just
using SimpleDateFormats that do what you want.


Let's talk some more, if you don't have access to code which get
the users input from the GUI and converts to a java.util.Date.

Note: the warnings about users with poorly set machines still
applies when you do this on the client. Typical problems are
valid TZs but mis-set times (I move from NYC to Berlin, but reset
my clock instead of resetting the timezone), or a variation which
is surprisingly common running on GMT timezone, but setting the clock
to display local time.

Another problem, you particular choice of format for input -- using
slashes -- is exactly the one that varies from country to country.

If you have separate fields on your GUI then set the TZ of a calendar
object (set the time to zero to zero all fields) then push the right
field values in do a cal.getTime() (use a sdf as above to test that your
are doing the right things to the value)

HTH,
-Paul

you are assuming that everyone types the date in the same format as yourself,
here in China it is:
YY/MM/DD

so 07/04/06 , is a perfectly valid date anywhere in the world, but DOES not
mean what you think it does.
and even in Europe & the states we have
04/06/06
06/04/06
which could mean the same thing , or may not depending on the locale

Basically client /server apps ,that take a time from a client , are asking
to fall over.


Steve
 
S

steve

Cheers Paul,

I understand the conversion but confused about where they are
performed. Considering I can only send longs between client and server,
the server has no timezone info about the client, the server could also
be in any timezone and it has to be stored in the DB as a date, are you
suggesting (for a "round trip"):

1.the user entry is converted to a long using d.getTime and sent to the
server
2.the server uses sdfGMTLots to convert to a date and stores this in
the DB
3.the server gets the date from the DB and converts to a long somehow
4.the client uses sdfLocalLots to convert the long and display the date

Step 3 I'm not sure about, if the date in the DB is GMT and the server
could be anywhere, how would it generate the correct long to be sent to
clients?

Cheers, Richard.

simple, you know or can pass the users GMT+- value, your server will also
have an available GMT+- value.

for speed
take your servers time , do (+-) to it to get GMT , then do(+-) to the
clients offset to GMT to get the clients correct time.
 
S

steve

I hope so, because my solution did NOT require the use of the sdfLots on
the server. The sdfLots was only used to peek inside the date object
and see what datetime it had including the hh:mmm:ss. It is never part
of the solution flow.

My solution was to treat the input as a date in UTC and pass that around.

What this really is a substitute for a datatype that you sometimes see
in other type collections, a datetime without NO timezone, not UTC.

The following statement contains such a no timezone datetime.
"All of Employees of Acme Corporation are welcome to go home
and party in remembrance of birthday of our founder at 5:00 PM on
Friday."

The following statement contains a GMT time:
"All managers in the FooBar project should be on the conference
call at 8 PM GMT."

The first is a set of that look the same as local times.

-Paul


It is sometimes frightning what people will do to , to get a solution to a
simple problem.
All we can do is give recommendations and hope that it all turns out fine in
the end.

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,781
Messages
2,569,619
Members
45,312
Latest member
Svsdvsdvs

Latest Threads

Top