The following code is giving me the parsed date as "Wed Jan 13 00:00:00 EST 2010"
instead of "Wed Jun 13 00:00:00 EST 2010". Any ideas much appreciated.
SimpleDateFormat sf = new SimpleDateFormat("yyyy-mm-dd'T'HH:mm:ss");
String str = "2010-06-13T00:00:00";
Date date = sf.parse(str);
System.out.println(" Date " + date.toString());
Try:
"yyyy-MM-dd'T'HH:mm:ss"
MM means month. mm means minutes. See the documentation for SimpleDateFormat for more details of the supported date and time patterns.
The problem is that you're using 'mm' as month and 'mm' represents minutes.
Below is all date formats available, read more doc here.
Symbol Meaning Kind Example
D day in year Number 189
E day of week Text E/EE/EEE:Tue, EEEE:Tuesday, EEEEE:T
F day of week in month Number 2 (2nd Wed in July)
G era designator Text AD
H hour in day (0-23) Number 0
K hour in am/pm (0-11) Number 0
L stand-alone month Text L:1 LL:01 LLL:Jan LLLL:January LLLLL:J
M month in year Text M:1 MM:01 MMM:Jan MMMM:January MMMMM:J
S fractional seconds Number 978
W week in month Number 2
Z time zone (RFC 822) Time Zone Z/ZZ/ZZZ:-0800 ZZZZ:GMT-08:00 ZZZZZ:-08:00
a am/pm marker Text PM
c stand-alone day of week Text c/cc/ccc:Tue, cccc:Tuesday, ccccc:T
d day in month Number 10
h hour in am/pm (1-12) Number 12
k hour in day (1-24) Number 24
m minute in hour Number 30
s second in minute Number 55
w week in year Number 27
G era designator Text AD
y year Number yy:10 y/yyy/yyyy:2010
z time zone Time Zone z/zz/zzz:PST zzzz:Pacific Standard
Modern answer:
String str = "2010-06-13T00:00:00";
LocalDateTime dateTime = LocalDateTime.parse(str);
System.out.println("Date-time " + dateTime);
Output:
Date-time 2010-06-13T00:00
I am using and recommending java.time, the modern Java date and time API. We don’t even need an explicit formatter for parsing. This is because your string is in ISO 8601 format, the international standard that the java.time classes parse as their default. java.time came out in 2014.
While in 2010 when this question was asked, SimpleDateFormat was what we had for parsing dates and times, that class is now considered long outdated, fortunately, because it was also troublesome.
In case your string contained only a date without time of day, use the LocalDate class in quite the same manner (this was asked in a duplicate question).
String dateStr = "2018-05-23";
LocalDate date2 = LocalDate.parse(dateStr);
System.out.println(date2);
2018-05-23
Link: Oracle tutorial: Date Time explaining how to use java.time.
Example if Date is 06 07 2016
SimpleDateFormat sdf= new SimpleDateFormat("dd MM yyyy");
you can use comma, full-stop, slash, or hyphen between these format.
Ex: dd-mm-yyyy, it will display like(06-07-2016)
dd/mm/yyyy,it will display like(06/07/2016)
dd.mm.yyyy,it will display like(06.07.2016)
dd,mm,yyyy ,it will display like(06,07,2016)
MM - will display number of the Month.
MMM - will display Month Three character only(Ex: Jul)
MMMM - will display full month(Ex: July)
yyyy - will display full year(2016)
yy - will display last two digits(16)
hh - will display hours
mm -will display minutes
ss - will display seconds
a - will display AM or PM
Ex: if time is 12:09:10 PM means (hh:mm:ss a)
EEE- will display short week name(Ex: Wed)
EEEE- will display full week name(Ex: Wednesday)
Related
I have some strings in Java that come in the format: Day Month Year Hour:Minute:Second
7 Jan 2010 23:00:00.000
4 Feb 2010 17:40:00.000
What is the easiest way to parse this string and convert the values to their resulting Julian Dates? I am reading in these strings from Excel so they are not objects with any sort of conversion/formatting utilities (just raw strings). Is there an easy library or function to call to convert these, or would I have to manually write a parser? Thanks
java.time
Sure, Java has got a parser for date and time built-in, the DateTimeFormatter class (named so because it can also format date and time back to strings). And a number of classes that can utilize it for producing objects of themselves. In your case you need the LocalDateTime class. A LocalDateTime is a date and time of day without time zone or offset from UTC, so appropriate for holding the data from your string.
This formatter s good for your string:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("d MMM uuuu HH:mm:ss.SSS", Locale.ENGLISH);
Edit: You wrote in a comment:
Plugging in Jan 7 2010 hour 23 into this calculator:
aavso.org/jd-calculator gives
back 2455204.45833. Would this be the exact Julian Date? I believe
your solution was giving the Day instead of Date decimal value
Yes, that’s exactly true. The modified code to get the julian date including the fraction is:
String source = "7 Jan 2010 23:00:00.000";
LocalDateTime ldt = LocalDateTime.parse(source, FORMATTER);
// Subtract half a day to compensate for the
// fact that the Julian day begins at noon
LocalDateTime dateToUseForJulianDay = ldt.minusHours(12);
long julianDayNumber = dateToUseForJulianDay.getLong(JulianFields.JULIAN_DAY);
double juianDateFraction = (double) dateToUseForJulianDay.getLong(ChronoField.NANO_OF_DAY)
/ (double) Duration.ofDays(1).toNanos();
double julianDate = julianDayNumber + juianDateFraction;
System.out.println("Julian date: " + julianDate);
And the output is in this example:
Julian date: 2455204.4583333335
It agrees very nicely with thee result you quote from the online calculator.
The Julian day number is the day number since January 1, 4713 BC. The Julian day starts at noon, which Java does not take into account, so as a hack I have subtracted 12 hours to compensate and get the correct day for all times of day. Since the getLong() method only gets the Julian day number as a whole number, I need to find the fraction separately. It’s a matter of dividing the nanosecond of the day by the total number of nanoseconds in a day. From the original date and time we would have needed the number of nanos since 12 noon; but since I have already subtracted 12 hours, the nanosecond of the day, since 0:00 midnight, is the number we need.
Further link: Julian day on Wikipedia
My library Time4J supports Julian Dates out of the box.
ChronoFormatter<PlainTimestamp> f =
ChronoFormatter.ofTimestampPattern(
"d MMM uuuu HH:mm:ss.SSS", PatternType.CLDR, Locale.ENGLISH);
Moment j2000 = f.parse("7 Jan 2010 23:00:00.000").atUTC(); // are your timestamps really UTC?
// eventually also: ".in(Timezone.ofSystem());"
System.out.println(JulianDay.ofSimplifiedTime(j2000)); // programmer's standard
// JD(POSIX)2455204.4583333335
System.out.println(JulianDay.ofEphemerisTime(j2000)); // astronomical definition
// JD(TT)2455204.459099352
Advantages:
No complex calculation of your owns.
Support for the astronomical definition on the time scale TT.
Explicit display of time zone dependencies (whatever you choose).
This question already has answers here:
SimpleDateFormat producing wrong date time when parsing "YYYY-MM-dd HH:mm"
(5 answers)
Closed 4 years ago.
I want to convert 2018-02-21 15:47:35 UTC to epoch UTC form. How do we do it? I am currently in PST.
SimpleDateFormat df = new SimpleDateFormat("YYYY-MM-DD HH:MM:SS");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
date = df.parse(dateString).getTime();
The code above should return the number of milliseconds since January 1, 1970, 00:00:00 GMT, but I'm getting an incorrect value.
The only problem with your code is DateFormat
please check.
https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
String dateString = "2018-02-21 15:47:35";
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
Date date = df.parse(dateString);
long time = date.getTime();
System.out.println(time);
System.out.println(new Date(time));
System.out.println(date);
I'm in PKT so output would differ...
1519228055000
Wed Feb 21 20:47:35 PKT 2018
Wed Feb 21 20:47:35 PKT 2018
Expected: 2018-02-21 15:47:35 UTC is equivalent to 1 519 228 055 000 milliseconds since the epoch of January 1, 1970 at 0:00 UTC.
Observed: Your code in the question gives 1 514 818 800 035. So it’s 4 409 254 965 milliseconds off, a little over 51 days.
The solution:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
date = LocalDateTime.parse("2018-02-21 15:47:35", dtf)
.atOffset(ZoneOffset.UTC)
.toInstant()
.toEpochMilli();
This gives the correct 1 519 228 055 000.
What went wrong?
One of the many troublesome traits of SimpleDateFormat is that with its default settings, if you specify an incorrect format pattern string, it will very often give you an incorrect result and pretend all is well. The modern Java date and time API that I am using in my snippet, is trying somewhat harder to figure out when the pattern doesn’t make sense and tell you it’s wrong somehow. As an example, let’s try your format pattern with the modern DateTimeFormatter:
final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("YYYY-MM-DD HH:MM:SS");
LocalDateTime.parse(dateString, dtf);
This will throw a java.time.format.DateTimeParseException: Text '2018-02-21 15:47:35' could not be parsed at index 14. Index 14 is where 47 is in the string, it was supposed to be the minutes. Apparently 47 doesn’t match MM in the format. If you haven’t figured out yet, check the documentation. It says that uppercase M is for “month-of-year”. So what the formatter is trying to tell you is there are not 47 months in a year. In the documentation you will also find lowercase m for “minute-of-hour”. As you correct the case of the letters in the format pattern string, you will receive other exceptions until you end up with either yyyy-MM-dd HH:mm:ss or uuuu-MM-dd HH:mm:ss (lowercase yyyy is year or era while uuuu is a signed year, both work for years after year 0).
Links
Oracle tutorial: Date Time explaining how to use java.time.
DateTimeFormatter documentation spelling out the uppercase and lowercase letters of format pattern strings.
Also can be done via java8 time library:
String dateString = "2018-02-21 15:47:35";
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
dateTimeFormatter.withZone(ZoneId.of("UTC"));
LocalDateTime parsedDateTime = LocalDateTime.from(dateTimeFormatter.parse(dateString));
ZonedDateTime timeAtYourZone = parsedDateTime.atZone(ZoneId.systemDefault());
System.out.println(timeAtYourZone.toInstant().toEpochMilli());
System.out.println(timeAtYourZone);
Your pattern must be yyyy-MM-dd HH:mm:ss, as the other answers told you:
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
I just want to add some more details.
First of all, take a look at the patterns description in the javadoc: https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Note that a lowercase y is not the same as the uppercase Y (lowercase is the year, while uppercase is the week year - 2 different fields with completely different definitions)
Also note that uppercase D is the day of the year, while the day of the month (which is what you want) is the lowercase d. And uppercase M is the month, while lowercase m is the minute of hour.
And uppercase S is the milliseconds field, while the seconds are represented by lowercase s.
And SimpleDateFormat's design doesn't help: the class simply tries to parse the string, even if the month field (MM) appears twice in your pattern, while the minutes field doesn't appear (and it's set to a default value of zero - all behind the scenes, without any warning, no indication of error at all).
Conclusion: always read the docs :-)
For Java 8 or higher, consider using the new date API, which is much better because it doesn't have all these behind-the-scenes stuff:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
.withZone(ZoneOffset.UTC);
long epochMilli = Instant.from(fmt.parse("2018-02-21 15:47:35")).toEpochMilli();
This API will also throw an exception if you use a pattern like YYYY-MM-DD HH:MM:SS, because it will try to parse the minutes value 47 as a month (because uppercase MM will be in the respective position), and 47 is not a valid month.
This question already has answers here:
How to convert "Mon Jun 18 00:00:00 IST 2012" to 18/06/2012?
(5 answers)
Closed 5 years ago.
I have a problem with date converting. I use the following program and I expect the output: 19.05.2017
But the output is: 05.00.2017
Can anybody help?
String t = "Fri May 19 00:00:00 CEST 2017";
Date d = new SimpleDateFormat("EEE MMM DD hh:mm:ss zzzz YYYY", Locale.US).parse(t);
String s = new SimpleDateFormat("dd.mm.yyyy").format(d).toString();
System.out.println(s);
A surprising result. The oldfashioned classes SimpleDateFormat and friends are full of surprises. This is meant as a negative thing.
Uppercase DD is day of year. Lowercase hh is hour of AM or PM (1 through 12). Uppercase YYYY is weekbased year (only useful with week number). So you are asking for a date that is a Friday in May and the 19th day of the year. Obviously this is not possible.
The result of parsing is Thu Jan 05 23:00:00 CET 2017. Apparently SimpleDateFormat opts for giving you a Friday and for using the zone offset of 2 hours implied by CEST even though the date it has chosen is not at the time of year where CEST (summer time) is in use. I don’t know whether it just gives you the first Friday of the weekbased year (Friday in week 1 of the year). Friday at 0000 hours at offset GMT+2 equals Thursday at 23 at GMT+1, which is CET.
Next for the formatting, 05 is the date as expected, but lowercase mm means minutes. Since the minutes are 0, you get 00. You got the right year.
Rather than using the outdated classes that give you such surprises, I agree with Sam’s answer that you should use the newer classes in java.time:
ZonedDateTime dt = ZonedDateTime.parse(t,
DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss zzz yyyy", Locale.US));
String s = dt.format(DateTimeFormatter.ofPattern("dd.MM.uuuu"));
This code gives you 19.05.2017 as you had expected. One of the good things about the modern classes is, if you try to parse with your original format pattern string, you will get a DateTimeParseException so you will know something is wrong. I certainly prefer an exception over incorrect output.
Another good thing is these classes respect the time zone in the input and use it in the output too (unless you explicitly instruct them otherwise). They will never turn Friday 6 January into Thursday 5 January because of some funny time zone issue.
Your input date is in Central European Summer Time and your date format is a bit wrong. Try
SimpleDateFormat input = new SimpleDateFormat("EEE MMM dd hh:mm:ss zzzz yyyy");
You might want to set the timezone on the output date format in order to get the date in the correct local time.
Ideally you'd move over to use a java.time style as shown here:
https://www.mkyong.com/java/java-convert-date-and-time-between-timezone/
Here's my code:
java.util.Date TODAY = new java.util.Date();
SimpleDateFormat SDF = new SimpleDateFormat( "YYYY-MM-DD" );
System.out.println ( SDF.format( TODAY ) );'
And the result is:
2015-02-33
But today's date is 2015-02-02!
What may be the reason behind this wrong output?
You want to use the yyyy year and dd day of the month.
However, I suggest you migrate to JSR-310 which is built into Java 8 and available for earlier versions of Java. The same code is
System.out.println(LocalDate.now());
prints
2105-02-02
What may be the reason behind this Wrong Output ?
Your assumptions about the date format string are wrong, the output is correct.
y Year
Y Week year
D Day in year
d Day in month
M Month in year
m Minute in hour
http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Y Week year will usually give incorrect results around new year. D will give incorrect results from February. So your format appeared fine most of last month.
When format for SimpleDateFormat is specified as follows:
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD");
the YYYY - means week year,
the MM - means month,
the DD - means day in year.
Week year here is not what you wanted. See what is week year.
Your today's date is 2015-02-02, which means that it is 32 days since the beginning of the year 2015 passed and your are on the 33 day. That is why you get date "2015-02-33".
To mean year (and not week year) and day in month change format to SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat dateFormat = new SimpleDateFormat("mm/dd/yyyy");
Date date = dateFormat.parse("11/04/2011");
System.out.println(date);
System.out.println(dateFormat.format(date));
Tue Jan 04 00:11:00 IST 2011
11/04/2011
When output the date object it shows as january instead of november. But when format the same date object it shows november correctly.
By making MM/dd/yyyy it both shows the correct result. But Shouldnt the mm/dd/yyyy throws an Unparseable date exception if mm/dd/yyyy is fishy?
A common error: mm is the pattern for minutes. You want to use MM to parse/print the month. Use MM/dd/yyyy instead of mm/dd/yyyy.
Since you parse the value 11 into the minute-part of the date and then print the minute-part of the date in the first place, the result of dateFormat.format(date) looks correct.
mm/dd/yyyy change it to MM/dd/yyyy
Letter Date or Time Component Presentation Examples
M Month in year Month July; Jul; 07
m Minute in hour Number 30
See
API Doc
Please note that Date is deprecated. You should use the Calendar class instead.
It is not fishy, capitalized M means Month in year and uncap m means Minute in hour
consult to this http://download.oracle.com/javase/6/docs/api/index.html?java/text/SimpleDateFormat.html