Situation: There is an Object AuditLog, which contains the variable java.util.Date date. This Object is saved in a mySQL Database.
#Entity
public class AuditLog implements Persistable<Long> {
...
#Temporal(TemporalType.DATE)
private Date date;
...
}
I am writing some JUnit tests and need to verify that a saved Date equals the actual date. Where date is a local Copy of the value actually passed to the log Object before it got saved and then loaded again.
Assert.assertEquals(date, log.getDate());
Output:
expected:<Wed May 24 15:54:40 CEST 2017> but was:<2017-05-24>
So you can see that the date actually is the right one but only y-m-d
I then tried this (below) to check if the milliseconds get altered.
Assert.assertEquals(date.getTime(), log.getDate().getTime());
Output:
expected:<1495634973799> but was:<1495576800000>
Now i think the best way would be to get the Milliseconds for year month day only.
Question: Can this be achieved relatively simple and should i do this? I think the Date gets altered because of a Database operation of some kind, so adapting the Test is OK right?
There are two ways to do this:
Using local date : You can convert util Date to LocalDate and do assertEquals on both the objects. LocalDate won't have time, e.g.:
Date input = new Date();
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
System.out.println(date);
Using Apache commons' DateUtils: You can use truncate method to set non date fields to zero, e.g.:
Date input = new Date();
Date truncated = DateUtils.truncate(input, Calendar.DATE);
System.out.println(truncated);
Here's the maven dependency for Apache commons library.
You can get the "just the day, month, year by using the following code:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class Answer {
public static void main(String args[]) throws ParseException {
// parse the date and time
String input = "Wed May 24 15:54:40 CEST 2017";
SimpleDateFormat parser = new SimpleDateFormat("EEE MMM d HH:mm:ss zzz yyyy");
Date date = parser.parse(input);
// parse just the date
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
formatter.setTimeZone(TimeZone.getTimeZone("CEST"));
String formattedDate = formatter.format(date);
Date parsedDate = formatter.parse(formattedDate);
System.out.println(parsedDate);
// use https://currentmillis.com/ to check the milliseconds figures
System.out.println("Wed May 24 15:54:40 CEST 2017 in milliseconds \t" + date.getTime());
System.out.println("Wed May 24 00:00:00 CEST 2017 in milliseconds \t" + parsedDate.getTime());
}
}
The second SimpleDateFormat("yyyy-MM-dd"); parses on the year-month-day.
Use Date.getTime()); to get the milliseconds.
The output is:
Wed May 24 15:54:40 CEST 2017 in milliseconds 1495634080000
Wed May 24 00:00:00 CEST 2017 in milliseconds 1495584000000
1495584000000 = Wed May 24 2017 00:00:00 (using https://currentmillis.com/)
Calendar cal = GregorianCalendar.getInstance();
cal.set(Calendar.YEAR, 2017);
cal.set(Calendar.MONTH, 5 - 1);
cal.set(Calendar.DAY_OF_MONTH, 24);
cal.set(Calendar.MILLISECOND, 0);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Date d = cal.getTime();
System.out.println(d.getTime());
this code creates a new java.util.Date with only year, month and day set. result of this example is 1495576800000 which is what you want.
A shorter way would be this:
Date d = new Date(0l);
d.setYear(117);
d.setMonth(4);
d.setDate(24);
d.setHours(0);
You should format the two dates:
Date date = new Date();
SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd");
dt.format(date);
Then compare each other.
Related
This question already has answers here:
How can I increment a date by one day in Java?
(32 answers)
SimpleDateFormat ignoring month when parsing
(4 answers)
Closed 4 years ago.
I wish to add one day to a given date.If i pass 2018-08-05,the below method returns 2018-08-06 which is expected. But if the pass the last date of the month -2018-08-31,it returns 2018-08-01 instead of expected result 2018-09-01.
DateFormat format = new SimpleDateFormat("yyyy-mm-dd", Locale.ENGLISH);
Date date = null;
try {
date = format.parse("2018-08-31");
} catch (ParseException e) {
}
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE ,1);
return format.format(cal.getTime());
You're using the old calendar/date API. This API is quite bad (it does weird things and does not accurately model how dates actually work).
It has been replaced with the new java.time API. I strongly suggest you use that instead. If you're on java7 or below, you can use the 'JSR310-backport' library to your dependency list to use this API. (JSR310 is the name for this addition to java).
In java.time, you'd do:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Test {
public static void main(String[] args) {
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate date = LocalDate.parse("2018-08-31", fmt);
System.out.println(fmt.format(date.plusDays(1)));
// yyyy-MM-dd so happens to be the default for LocalDate, so...
// we can make it a lot simpler:
date = LocalDate.parse("2018-08-31");
System.out.println(date.plusDays(1));
}
}
The bug is in the pattern of your SimpleDateFormat which you use for input and output. This dual-use masks the error:
public class Main {
public static void main(String[] args) throws Exception {
DateFormat format = new SimpleDateFormat("yyyy-mm-dd", Locale.ENGLISH);
Date date = format.parse("2018-08-31");
System.out.println("format: " + format.format(date) +", real: " + date);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.DATE ,1);
System.out.println("format: " + format.format(cal.getTime()) +", real: " + cal.getTime());
}
}
This gives you:
format: 2018-08-31, real: Wed Jan 31 00:08:00 CET 2018
format: 2018-08-01, real: Thu Feb 01 00:08:00 CET 2018
Using the right pattern yyyy-MM-dd produces the right answer:
format: 2018-08-31, real: Fri Aug 31 00:00:00 CEST 2018
format: 2018-09-01, real: Sat Sep 01 00:00:00 CEST 2018
Since the new and the old Java-Time API use the same patterns, simply adopting the new API will not help in this case.
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date date = null;
try {
date = format.parse("2018-08-31");
} catch (ParseException e) {
}
Calendar cal = new GregorianCalendar();
cal.setTime(date);
cal.setTimeInMillis(cal.getTimeInMillis() + 86400000); //86400000ms = 1 day
return format.format(cal.getTime());
I am trying to correct a date with some offset value according to the time zone. So, when I format a timestamp with a time zone offset, I expected that SimpleDateFormat will add the offset value to the time.
Here is what I tried:
package com.krishna.mytrials;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class DateExperiments {
public static void main(String[] args) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//Date we set in UI
Date today = new Date();
//The long value
String todayBrowserLocalTimeStamp = sdf.format(today);
System.out.println(todayBrowserLocalTimeStamp);
Date todayBrowserLocalTimeStampDate = sdf.parse(todayBrowserLocalTimeStamp);
System.out.println("Today's browser local time stamp: " + todayBrowserLocalTimeStampDate);
System.out.println("And its long value:" + todayBrowserLocalTimeStampDate.getTime());
System.out.println("Date generate from long:"+ new Date(todayBrowserLocalTimeStampDate.getTime()));
//What server does to the above mid night time stamp of browser-local time zone
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
//What we get after it applied the server time zone to browser-local date
//### This is the wrong date
SimpleDateFormat sdf2 = new SimpleDateFormat();
sdf2.setTimeZone(TimeZone.getTimeZone("GMT"));
sdf2.applyPattern("yyyy-MM-dd HH:mm");
System.out.println(sdf2.format(todayBrowserLocalTimeStampDate));
String utcDateString = sdf.format(todayBrowserLocalTimeStampDate);
System.out.println("The above mid night time stamp of browser-local time zone"
+ "is converted to GMT.### The wrong one:");
System.out.println(utcDateString);
//### The wrong date constructed
Date utcDate = sdf.parse(utcDateString);
System.out.println("###Wrong date:"+utcDate);
//### The wrong long
Long utcLong = utcDate.getTime();
System.out.println("###Wrong long:"+utcLong);
// What we will do with the GMT+05:30
sdf.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
String dateToBeCorrected = sdf2.format(todayBrowserLocalTimeStampDate);
System.out.println("Date to be corrected:"+ dateToBeCorrected);
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date correctedDate = sdf3.parse(dateToBeCorrected);
System.out.println(correctedDate);
SimpleDateFormat sdf4 = new SimpleDateFormat();
sdf4.setTimeZone(TimeZone.getTimeZone("IST"));
String correctedString = sdf4.format(correctedDate);
System.out.println("Corrected date:" + formatDateToString(correctedDate,"dd MMM yyyy hh:mm:ss a", "IST"));
}
public static String formatDateToString(Date date, String format,
String timeZone) {
// null check
if (date == null) return null;
// create SimpleDateFormat object with input format
SimpleDateFormat sdf = new SimpleDateFormat(format);
// default system timezone if passed null or empty
if (timeZone == null || "".equalsIgnoreCase(timeZone.trim())) {
timeZone = Calendar.getInstance().getTimeZone().getID();
}
// set timezone to SimpleDateFormat
sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
// return Date in required format with timezone as String
return sdf.format(date);
}
}
Here is the output:
2017-01-12
Today's browser local time stamp: Thu Jan 12 00:00:00 IST 2017
And its long value:1484159400000
Date generate from long:Thu Jan 12 00:00:00 IST 2017
2017-01-11 18:30
The above mid night time stamp of browser-local time zoneis converted to GMT.### The wrong one:
2017-01-11
###Wrong date:Wed Jan 11 05:30:00 IST 2017
###Wrong long:1484092800000
Date to be corrected:2017-01-11 18:30
Wed Jan 11 18:30:00 IST 2017
Corrected date:11 Jan 2017 06:30:00 PM
It is supposed add 05:30. to the date. What am I doing wrong?
You have to consider that roundtrips using formatting and parsing can loose informations. This is due to the fact that a formatted date might contain less informations than the original Date-instance had. Look at this data loss:
Original timestamp (variable todayBrowserLocalTimeStampDate) was: 2017-01-11 18:30 (in UTC) or as long: 1484175600000L
String utcDateString = sdf.format(new Date(1484175600000L));
// 2017-01-11
Date utcDate = sdf.parse(utcDateString);
Here you strip away the time part AND parse the stripped string again. Of course, the resulting new Date-instance must loose the corresponding time part, too, and cannot be the same as before.
2017-01-11 (with zero time) would be rendered in your IST-zone 5:30 hours later, that is: 2017-01-11T05:30+05:30 (remember: Date.toString() uses your IST-zone assuming that is your system zone). This is same instant as 2017-01-11T00:00Z. All is fine, only your expectation expressed in line indicated by prefix ###Wrong date is wrong.
I am trying to return a validity date, or an expiration date for a file, if you will. Currently, I have a sample program that prints out all the needed information but nnot exactly in the format I get. My code prints out:
Thu May 15 04:57:36 PDT 2014
But I need it to print out like so:
Thu, 15 May 2013 04:57:36 PDT
As you can see, very similar just not quite in the right place. Here is my test code that gives me the first result:
import java.util.Calendar;
import java.util.Date;
public class TestCalendar{
public static void main(String[] args){
Calendar currentDate = Calendar.getInstance();
currentDate.setTime(new Date());
currentDate.add(Calendar.MINUTE, 24);
Date newDate = currentDate.getTime();
System.out.println("Date: " + newDate);
}
}
This code adds 24 minutes to the current time and then prints it out, I just cant figure out how to reformat this date. SimpleDateFormat doesn't seem like it's going to work but I could be wrong. I just couldn't figure it out.
Thanks in advance for any help anyone is able to give me!!
Use SimpleDateFormat:
DateFormat formatter= new SimpleDateFormat("E, d MMM yyyy hh:mm:ss zzz");
Calendar currentDate = Calendar.getInstance();
currentDate.setTime(new Date());
currentDate.add(Calendar.MINUTE, 24);
Date newDate = currentDate.getTime();
System.out.println(formatter.format(newDate));
System.out.println("Date: " + newDate);
invokes toString() on Date instance, which has fixed format, you can't modify that
what you need is to format() your Date instance to String using SimpleDateFormat
This question already has answers here:
Is java.util.Date using TimeZone?
(5 answers)
Closed 7 years ago.
String = 26/8/2013 15:59;
I want to convert this date into GMT, however after applying the below code, I get the EEST time rather than the GMT.
DateFormat df = new SimpleDateFormat("dd/MM/yyyy h:m");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
df.parse(newDate);
Log.i(tag, df.parse(newDate).toString());
Output :
Mon Aug 26 18:59:00 EEST 2013
Whats wrong ?
Your parsing is correct, the different is just for your locale time zone that is used to display when you are making toString(). I just used formatted output to demonstrate the correct format . Here is the details example:
final String time = "26/8/2013 15:59";
TimeZone timeZone = TimeZone.getTimeZone("UTC");
final String REQUEST_DATE_FORMAT = "dd/MM/yyyy h:m";
DateFormat format = new SimpleDateFormat(REQUEST_DATE_FORMAT);
Date localDate = format.parse(time);
// localDate.toString()
// PRINT. Mon Aug 26 15:59:00 EEST 2013
Calendar cal = Calendar.getInstance(timeZone);
cal.setTime(localDate);
format.setTimeZone(timeZone);
final String utcTime = format.format(cal.getTime());
// PRINT. 26/08/2013 12:59
Nothing's really wrong. You are successfully parsing the datetime string interpreted as UTC timezone.
When printing it to log, you get what you ask for - Date.toString() returns the date formatted to current locale settings which include the timezone. The difference between UTC and EEST is 3 hours.
If you want to to format it to display some other timezone, pass it though format() of a SimpleDateFormat that is configured to the timezone you want.
I think you should use the below approach:
Date myDate = new Date();
Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(TimeZone.getTimeZone("UTC"));
calendar.setTime(myDate);
Date time = calendar.getTime();
SimpleDateFormat outputFmt = new SimpleDateFormat("MMM dd, yyy h:mm a zz");
String dateAsString = outputFmt.format(time);
System.out.println(dateAsString);
I have a string (Jan12) (generated by applying some operations on current date {20-jan-2012}) Now i want to convert back this string into Date format . Also the value should be same i.e the new Date object should have value jan12 and not (20-jan-2012) . Pls help . I have tried doing
java.sql.Date.valueOf("Jan12") [this throws IllegalArgumentException]
and also
new SimpleDateFormat("MMMyy").parse("Jan12") [By this Date gets converted to 20-jan-2012]
Output required : A Date Object having value Jan12 (12 is the year)
My Code : new java.text.SimpleDateFormat("MMMyy").format(new java.text.SimpleDateFormat("yyyy-MM-dd").parse(s)) // It is a string which gives Jan12
Now i really want to convert Mycode into a Date object
Date now = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String s1 = df.format(now);
System.out.println(s1); // 2012-01-20
java.sql.Date d111=java.sql.Date.valueOf(s1);
System.out.println(d111); // 2012-01-20
DateFormat df1 = new SimpleDateFormat("MMMyy");
String s2 = df1.format(d111);
System.out.println(s2); //Jan12
Now i want s2 to be converted in Date object
#Aditya,
If you use the Str2 which gives "Jan12", there is no date part in that string and therefore if you convert it to a date object, it will get "Jan" as month, 12 as year but it cant find "day" in that String.
if you use below code
try
{
Date d2 = df1.parse(s2); //here s2 is your string which gives "JAN12"
System.out.println(d2);
}
catch(ParseException pe)
{
System.out.println("parse exception..");
}
The output to the above code will be:
Sun Jan 01 00:00:00 IST 2012
notice here that day part is reset to the first day of the month
Therefore, it is not possible to get a complete date object as your original Date, the month and year are preserved, but the day part is lost.
What do you mean "gets converted"? How your Date is displayed is a separate issue. Look into formatting a Date.
So the 12 is day, not a year - you should parse it as such. Aslo, you'll need to tell it what year this is:
System.out.println(new SimpleDateFormat("yyyyMMMdd").parse("2012" + "Jan12"));
Output
Thu Jan 12 00:00:00 EST 2012
Use the SimpleDateFormat class properly, it will do exactly what you want
String str_date="12-Jan-2012";
DateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy");
Date date = (Date)formatter.parse(str_date);
Note: the formatter.parse() method throws ParseException, catch it;
If 12 is a year
Calendar calendar = Calendar.getInstance();
calendar.setTime(new SimpleDateFormat("MMMyy").parse("Jan12"));
calendar.set(Calendar.DATE, 1);
Date date = calendar.getTime(); // First Jan 2012
If 12 is a day
Calendar calendar = Calendar.getInstance();
calendar.setTime(new SimpleDateFormat("MMMdd").parse("Jan12"));
calendar.set(Calendar.YEAR, 2012);
Date date = calendar.getTime(); // 12 Jan 2012
I understand that you want to format your Date object into a String representation.
You can use SimpleDateFormat for this, analog to your second example:
Date d = new Date(112, 0, 20); //don't construct a date like this in production code, use a Calendar instance instead
String formattedDate = new SimpleDateFormat("MMMyy").format(d); // -> "Jan12"
Note that your Date object represents a specific point in time, it will always have a day and a time associated with it.
If you want to compare Dates with the resolution of a month, you have to set day and time to neutral values:
Calendar cal = Calendar.getInstance();
cal.setTime(d);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
d = cal.getTime();
Just extend Date and customize it to use your favourite parse & format methods.