I store dates on server side in UTC timezone.
When client (browser) wants to pass some date to server it sends date like
"Tue Jan 03 2012 16:50:32 GMT+0400 (Russian Standard Time)"
Is this format standard across all browsers?
If 1. is false, how can I redefine the Date format function? Is this a good practice?
How can I convert JS Dates to a UTC java.util.Date with java.text.SimpleDateFormat?
UPDATE
I thought that passing date as formatted string (with timezone part) will cause less headache since I shouldn't bother to convert dates to UTC on client side. So I avoid any date conversions in JS code.
You should send the number of milliseconds since epoch (1 Jan 1970 UTC) that is available via the + prefix operator as in +new Date(2012, 0, 1).
Sending anything with a timezone requires both machines to have the same timezone definitions which means you will likely end up with subtle bugs where two dates occurred in one order on one machine but in a different order on another. You can eliminate that whole class of bugs by using the millis since epoch representation.
To answer your questions:
Is this format standard across all browsers?
Date.prototype.toString and toUTCString are both implementation dependent but toISOString is reliable.
http://es5.github.com/#x15.9.5.43
15.9.5.43 Date.prototype.toISOString ( ) # Ⓣ Ⓡ
This function returns a String value represent the instance in time represented by this Date object. The format of the String is the Date Time string format defined in 15.9.1.15. All fields are present in the String. The time zone is always UTC, denoted by the suffix Z. If the time value of this object is not a finite Number a RangeError exception is thrown.
15.9.1.15 Date Time String Format # Ⓣ Ⓔ Ⓑ
ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ
Whereas http://es5.github.com/#x15.9.5.2 says
15.9.5.2 Date.prototype.toString ( ) # Ⓣ Ⓡ
This function returns a String value. The contents of the String are implementation-dependent, but are intended to represent the Date in the current time zone in a convenient, human-readable form.
http://es5.github.com/#x15.9.1.15
15.9.5.42 Date.prototype.toUTCString ( ) # Ⓣ Ⓡ
This function returns a String value. The contents of the String are implementation-dependent, but are intended to represent the Date in a convenient, human-readable form in UTC.
NOTE The intent is to produce a String representation of a date that is more readable than the format specified in 15.9.1.15. It is not essential that the chosen format be unambiguous or easily machine parsable. If an implementation does not have a preferred human-readable format it is recommended to use the format defined in 15.9.1.15 but with a space rather than a “T” used to separate the date and time elements.
I don't know whether this format is standardized for all browsers.
But you could use the getTime() function in JavaScript which returns the milliseconds since 1 January 1970 00:00:00 UTC and initializes the Java Date object with this value.
You could send the data in UNIX time format, maybe?
Related
So I have an object ('Task') that has an attribute 'Start Date' which is basically a Timestamp object. So this date is in this format 'YYYY/MM/dd hh:mm:ss:ms'. But for a test case I am authoring, I need this date to be in this format 'YYYY/MM/dd hh:mm'. Also it needs to be a timestamp object as I have to set this value back to the 'Task' object.
I have tried several approaches including the snippet shown below:
SimpleDateFormat formatter = new SimpleDateFormat("YYYY-MM-dd hh:mm");
if (task.getStartDate() != null) {
String newDate = formatter.format(task.getStartDate());
Date date = formatter.parse(newDate);
task.setStartDate(new Timestamp(date.getTime()));
}
I expected the value of the timestamp to be in the format '2018-12-30 09:54' but it resulted in '2018-12-30 09:54:00.0'. So the questions that I have in mind is:
Is there a way to not consider the seconds and millis in the Timestamp object?
If no, then, is the snippet provided an efficient way to update the Timestamp object?
TL;DR
Avoid the Timestamp class if you can. It’s poorly designed and long outdated.
To answer your questions, no, a Timestamp hasn’t got, as in cannot have a format (the same holds true for its modern replacement, Instant (or LocalDateTime)).
Under all circumstances avoid SimpleDateFormat and Date. The former in particular is notoriously troublesome, and both are long outdated too.
Don’t put a format into your model class
You should not want an Instant nor a Timestamp with a specific format. Good practice in all but the simplest throw-away programs is to keep your user interface apart from your model and your business logic. The value of the Instant object belongs in your model, so keep your Instant or Timestamp there and never let the user see it directly. I hope that it’s clear to you that 2018-12-30 09:54 and 2018-12-30 09:54:00.0 represent the same value, the same Timestamp. Just like 17, 0017 and 0x11 represent the same integer value. When you adhere to what I said, it will never matter which format the Instant has got.
Whenever the user should see the date and time, this happens in the UI, not in the model. Format it into a String and show the string to the user. Similarly if you need a specific format for persistence or exchange with another system, format the Instant into a string for that purpose.
java.time and JDBC 4.2
Also for exchange with your database over JDBC, provided that you’ve got a JDBC 4.2 compliant driver, prefer to use a type from java.time over Timestamp. If the datatype on the database side is timestamp with time zone, very clearly recommended for a timestamp, pass an OffsetDateTime like
OffsetDateTime dateTime = yourInstant.atOffset(ZoneOffset.UTC);
yourPreparedStatement.setObject(4, dateTime);
Use setObject, not setTimestamp. Some drivers accept the Instant directly, without conversion to OffsetDateTime. If on the database side you need a mere timestamp (without time zone), use LocalDateTime in Java instead and pass one to setObject in the same way as above.
PS There are errors in your format pattern string
In a format pattern string, uppercase YYYY is for week based year and only useful with a week number. For year use either uuuu or lowercase yyyy. Similarly lowercase hh is for hour within AM or PM from 01 through 12 and only useful with an AM or PM marker. For hour of day from 00 through 23 you need uppercase HH. These errors will give you incorrect dates and times in most cases. Using the wrong case of format pattern letters is a very common mistake. SimpleDateFormat generally doesn’t mind, it just gives incorrect results. The modern DateTimeFormatter does a somewhat better job of notifying you of such errors.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Related questions
Formatting timestamp in Java about getting rid of the .0 decimal on the second of a Timestamp.
timestamp formatting in scala [duplicate] about getting a Timestamp with only date and hour (no minute, second or fraction of second).
java parsing string to date about uppercase Y for year in a format pattern string.
Comparing two times in android about lowercase h for hour of day in a format pattern string.
If I use AMAZON.DATE as a slot type, the user is able to input all kind of dates. Stating from the documentation:
"2015-12", "2017-WI" (for winter of 2017) or "2015-W48-WE" (for weekend of week 48 of 2015). I want to parse these dates into Java dates/durations and I wonder how to achieve this.
Is there a Java library that takes a date like "2015-12" and returns two dates or a date and a duration?
I can see a lot of potential problems like time zone handling or ambiguous dates, but I hope this is a common problem.
I could write a parser to save it as two Dates, one for the beginning of the month and one for the end of the month. Or a date for the beginning and a duration, but this seems like a lot of overhead to comply with ISO 8601.
Amazon's Calendar Reader skill sample contains a JavaScript AMAZON.DATE parser that should be fairly easy to convert to other languages. It takes the slot value and returns a JavaScript Date object. According to the comments, it handles all of the idiomatic date formats.
// Utterances that map to the weekend for a specific week (such as 'this weekend') convert to a date indicating the week number and weekend: 2015-W49-WE.
// Utterances that map to a month, but not a specific day (such as 'next month', or 'December') convert to a date with just the year and month: 2015-12.
// Utterances that map to a year (such as 'next year') convert to a date containing just the year: 2016.
// Utterances that map to a decade convert to a date indicating the decade: 201X.
// Utterances that map to a season (such as 'next winter') convert to a date with the year and a season indicator: winter: WI, spring: SP, summer: SU, fall: FA)
You can use The Amazon date parser in Nodejs for converting it.
The amazon-date-parser is an useful npm package (more info here). It converts the AMAZON.DATE slot value to a JS object composed by a startDate and an endDate i.e.:
var AmazonDateParser = require('amazon-date-parser');
var date = new AmazonDateParser('2017-W48');
console.log(date);
Is there any function or library which gets a date in milliseconds, given a String?
This question shows how to convert a formatted String to a Date object, but is there any way to do this with an unformatted String?
Basically, the task is impossible. Here's an example:
01/04/2012
In the US, that means January 4th 2012. In Australia, that mean 1st April 2012.
Without knowing where you are and what date formats conventionally mean, it is impossible to accurately map an arbitrary date-like string to a date time value that matches what the user actually meant.
And even if you do know about the relevant local conventions, users have a remarkable propensity to be oblivious to ambiguity. Dealing with that may require deep domain knowledge (or mind reading skills!) to disambiguate the possible meanings.
When you think about it, this is why modern user interfaces typically use a date-picker widget of some kind when the user needs to enter a date / time
first convert the string to Date. From there you can get time in milis using Date.getTime() method
I have a PHP web service sending JSON responses back to my Java client. One of the fields is a DateTime value. However, I'm having problems translating the serialized PHP Date/Time to a Java Date.
For example, here is a date stored in my database:
2011-12-07 15:03:01
Here is how it's encoded in the JSON response:
1323288181
I suspected this would be the milliseconds since the Unix epoch, but when I construct a Java Date with that given value, the date turns out to be the following:
Fri Jan 16 01:34:48 CST 1970
Obviously it's not milliseconds since January 1, 1970 at midnight.
How do I go about doing this?
Looks like that's seconds since the Unix epoch - so just multiply your value by 1000 when passing it to the Date constructor.
Note that Date.toString() will always use the system time zone, but a Date really represents an instant in time, so it doesn't have a time zone.
If you're doing anything significant with dates and times, I'd thoroughly recommend using Joda Time instead of the classes in java.util.
I think it is a unixtimestamp. use this online convertor: http://www.onlineconversion.com/unix_time.htm
and here are examples how to convert it (in java):
http://www.epochconverter.com/
I am using
1970-01-01T00:00:00Z
as date time format in JSON,
then I make sure both sides parse it correctly
I need to store the timezone an email was sent from. Which is the best way to extract it from the email's 'Date:' header (an RFC822 date)? And what is the recommended format to store it in the database (I'm using hibernate)?
I recommend you use Mime4J.
The library is designed for parsing all kinds of email crap.
For parsing dates you would use its DateTimeParser.
int zone = new DateTimeParser(new StringReader("Fri, 27 Jul 2012 09:13:15 -0400")).zone();
After that I usually convert the datetimes to Joda's DateTime. Don't use SimpleDateFormatter as will not cover all the cases for RFC822.
Below will get you the Joda TimeZone (from the int zone above) which is superior to Java's TZ.
// Stupid hack in case the zone is not in [-+]zzzz format
final int hours;
final int minutes;
if (zone > 24 || zone < -24 ) {
hours = zone / 100;
minutes = minutes = Math.abs(zone % 100);
}
else {
hours = zone;
minutes = 0;
}
DateTimeZone.forOffsetHoursMinutes(hours, minutes);
Now the only issue is that the Time Zone you will get always be a numeric time zone which may still not be the correct time zone of the user sending the email (assuming the mail app sent the users TZ and not just UTC).
For example -0400 is not EDT (ie America/New_York) because it does not take Daylight savings into account.
Probably easiest to parse with JodaTime as it supports ISO8601 see Date and Time Parsing and Formatting in Java with Joda Time.
DateTimeFormatter parser2 = ISODateTimeFormat.dateTimeNoMillis();
System.out.println(parser2.parseDateTime(your_date_string));
Times must always be stored in UTC (GMT) with a timezone - i.e. after parsing convert from the timezone to GMT and remove daylight savings offset and save the original timezone.
You must store the date with the timezone after converting to UTC.
If you remove or don't handle the timezone it will cause problems when dealing with data that has come from a different timezone.
Extract the data from the header using some sort of substring or regular expression. Parse the date with a SimpleDateFormatter to create a Date object.
The timezone in the email will not show in which timezone it was send. Some programs use ever UTC or GMT. Of course the time zone is part of the date time value and must also be parse.
Why do you want know it.
- Do you want normalize the timestamp? Then use a DateFormat for parsing it.
- Do you want detect the timezome of the user that send the email? This will not correctly work.
It looks like you already mentioned this in one of your comments, but I think it's your best answer. The JavaMail library contains RFC822 Date header parsing code in javax.mail.internet.MailDateFormat. Unfortunately it doesn't expose the TimeZone parsing directly, so you will need to copy the necessary code directly from javax.mail.internet.MailDateParser, but it's worth taking advantage of the careful work already done.
As for storing it, the parser will give you the date as an offset, so you should be able to store it just fine as an int (letting Hibernate translate that to your database for you).