This question already has answers here:
Java Calendar adds a random number of milliseconds?
(4 answers)
Closed 2 years ago.
I am trying to format the date to ISO8601("yyyy-MM-dd'T'HH:mm:ss.SSSZ") using SimpleDateFormat, but formatted string seems to have random values at milliseconds place.
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class DemoApplication {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.set(2020, 5 , 22, 17, 30, 00);
Date date = calendar.getTime();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String s = df.format(date);
System.out.println(s);
}
}
Output on multiple runs:
2020-06-22T17:30:00.886+0530
2020-06-22T17:30:00.049+0530
2020-06-22T17:30:00.799+0530
In the above output, everything is consistent except milliseconds after dot(.), Can someone explain this?
In the above output, everything is consistent except milliseconds
after dot(.), Can someone explain this?
The reason is that your format has milliseconds but you haven't set milliseconds in the Calendar instance; therefore, it gives you the milliseconds of the moment when you run your code.
You can verify the same using the following code:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.set(2020, 5, 22, 17, 30, 00);
Date date = calendar.getTime();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String s = df.format(date);
System.out.println(s);
System.out.println(date.toInstant().getNano()); // Added this line
}
}
Output:
2020-06-22T17:30:00.425+0100
425000000
On a side note, I recommend you stop using outdated date-time API and start using the modern date-time API.
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
ZonedDateTime zdt = LocalDateTime.of(2020, 5, 22, 17, 30, 00).atZone(ZoneId.systemDefault());
System.out.println(zdt);
}
}
Milliseconds aren't covered by
calendar.set(2020, 5 , 22, 17, 30, 00);
you can an extra Line to set them to 0:
calendar.set(Calendar.MILLISECOND, 0);
so that your program looks like this:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class DemoApplication {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
calendar.set(2020, 5 , 22, 17, 30, 00);
calendar.set(Calendar.MILLISECOND, 0);
Date date = calendar.getTime();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String s = df.format(date);
System.out.println(s);
}
}
The JavaDocs of java.util.Calendar state the following for the method getInstance():
Gets a calendar using the specified time zone and default locale. The Calendar returned is based on the current time in the given time zone with the default locale.
That means you are getting the actual moment and then by calendar.set(2020, 5 , 22, 17, 30, 00); you set year, month, day, hours, minutes and seconds but you are not changing the smaller units of time which will stay as they were when you called Calendar calendar = Calendar.getInstance(TimeZone.getDefault());. That's not random, it's the current millis at that very moment of calling getInstance().
For a possibility of setting the milliseconds of a Calendar to any specific value, have a look at the answer given by #Norwort.
I think you shouldn't be using the outdated datetime classes from java.util. Instead, use java.time, maybe like this:
public static void main(String[] args) throws ParseException {
ZonedDateTime zonedDateTime = ZonedDateTime.of(2020, 5, 22, 17, 30, 0, 0,
ZoneId.systemDefault());
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
String s = zonedDateTime.format(dtf);
System.out.println(s);
}
Which prints
2020-05-22T17:30:00.000+0200
when executed on my system, which has an offset of +02:00 at the moment.
The output on your system might differ, but will have set milliseconds and smaller units of time to 0.
Related
I have this Time object:
Time myTime = java.sql.Time.valueOf("15:33:00");
How can I add 30 minutes to myTime in Java? That means the new time will be 16:03:00
java.sql.Time myTime = java.sql.Time.valueOf("15:33:00");
LocalTime localtime = myTime.toLocalTime();
localtime = localtime.plusMinutes(30);
String output = localtime.toString();
you can get localTime straight away from the java.sql.time and you can use plusMinutes in LocalTime Api to add 30 minutes. this might help you check this
Here's an easy way to do it, using java.time.LocalDateTime:
package time;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalField;
/**
* Created by Michael
* Creation date 4/24/2016.
* #link
*/
public class TimeDemo {
public static void main(String[] args) {
// Three three lines do the work
LocalDateTime localDateTime = LocalDateTime.of(2016, 4, 24, 9, 10);
LocalDateTime halfHourLater = localDateTime.plusMinutes(30); // Add 30 minutes
java.sql.Time sqlDateTime = new java.sql.Time(halfHourLater.toInstant(ZoneOffset.UTC).toEpochMilli()); //
// Printout just to check
System.out.println(DateTimeFormatter.ofPattern("yyyy-MMM-dd hh:mm:ss.SSS").format(halfHourLater));
System.out.println("java.time milliseconds: " + halfHourLater.toInstant(ZoneOffset.UTC).toEpochMilli());
System.out.println("System.currentMillis : " + System.currentTimeMillis());
}
}
According to the following website daylight saving time in UK starts from 27 Mar-2016 1:00:00 (24 hours time format)
http://www.timeanddate.com/time/change/uk/london?year=2016
Then why the following code prints false?
import java.text.ParseException;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class BSTGMTDetector
{
public static void main(String[] args) throws ParseException
{
TimeZone def = TimeZone.getTimeZone("Europe/London");
Calendar cal = new GregorianCalendar();
cal.clear();
cal.set(2016, 2, 27,2,01,01);
boolean isInDaylight = def.inDaylightTime(cal.getTime());
System.out.println("Date[" + cal.getTime() + "] is in DST[" + isInDaylight + "]");
}
}
Output : Date[Sun Mar 27 02:01:01 IST 2016] is in DST[false]
It seems that your system maintain IST.When you define,
Calendar cal = new GregorianCalendar();
Timezone for cal variable is IST.So,when call
def.inDaylightTime(cal.getTime());
Date is passed to this method in IST timezone.So,DST start for UK at 27th MAR,06:30:00 IST.
Hence.your O/P behaviour.
I am doing something like this in my program :
Calendar cal = DatatypeConverter.parseDateTime("2012-05-29T11:17:04.805-07:00");
System.out.println(cal.getTime().toString());
o/p:
Tue May 29 13:17:04 CDT 2012
Why is the result showing time of 13:17:04, in the input I have given 11:17:04 and time zone -07:00 which is pacific time zone. Should it not print out 11:17:04 ?
Your timezone - the default one when the program is running is different from the timezone given to the DatatypeConverter.parseDateTime() method and the cal.getTime().toString() method used the default timezone to format the date.
Never use Date.toString() to format Date - a Date only knows the milliseconds from the Epoch time. Instead use java.text.SimpleDateFormat like this:
SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").format(dateObject).
import java.util.Calendar;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
import javax.xml.bind.DatatypeConverter;
class TestDate
{
public static void main(String[] args)
{
Calendar cal = DatatypeConverter.parseDateTime("2012-05-29T11:17:04.805-07:00");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
df.setTimeZone(TimeZone.getTimeZone("GMT-07:00"));
String date = df.format(cal.getTime());
System.out.println(date);
}
}
I thought I'd be able to create a GregorianCalendar using the constructor that takes the year, month, and day, but I can't reliably get those fields from an instance of the java.sql.Date class. The methods that get those values from java.sql.Date are deprecated, and the following code shows why they can't be used:
import java.sql.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class DateTester {
public static void main(String[] args) {
Date date = Date.valueOf("2011-12-25");
System.out.println("Year: " + date.getYear());
System.out.println("Month: " + date.getMonth());
System.out.println("Day: " + date.getDate());
System.out.println(date);
Calendar cal = new GregorianCalendar(date.getYear(), date.getMonth(), date.getDate());
System.out.println(cal.getTime());
}
}
Here's the output, showing that the month and year are not returned correctly from the deprecated getYear() and getMonth() methods of Date:
Year: 111
Month: 11
Day: 25
2011-12-25
Thu Dec 25 00:00:00 EST 111
Since I can't use the constructor that I tried above, and there's no GregorianCalendar constructor that just takes a Date, how can I convert a java.sql.Date object into a GregorianCalendar?
You have to do this in two steps. First create a GregorianCalendar using the default constructor, then set the date using the (confusingly named) setTime method.
import java.sql.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class DateTester {
public static void main(String[] args) {
Date date = Date.valueOf("2011-12-25");
System.out.println(date);
Calendar cal = new GregorianCalendar();
cal.setTime(date);
System.out.println(cal.getTime());
}
}
Here's the output:
2011-12-25
Sun Dec 25 00:00:00 EST 2011
I'm going from memory, but have you tried
Calendar cal = GregorianCalendar.getInstance();
cal.setTime(rs.getDate());
Try this.
import java.sql.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class DateTester {
public static void main(String[] args) {
Date date = Date.valueOf("2011-12-25");
System.out.println(date);
Calendar cal = new GregorianCalendar();
cal.setTime(date);
System.out.println(cal.getTime());
}
}
Use setTimeInMillis():
java.sql.Date date = new java.sql.Date(System.currentTimeMillis());
Calendar cal = new GregorianCalendar();
cal.setTimeInMillis(date.getTime());
I think this is the simplest way.
Is there any way to format Date object to made fixed length of Day and Month in order to have good alignment in a column?
For example:
15 May 2010
10 January 2010
Instead of
15 May 2010
10 January 2010
Thanks!
Have a look at the java.util.Formatter class whose format method is the same as String.format(...) and similar to System.out.printf.
For example:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class FormatDateCalendar {
public static final String FORMAT_STRING = "%1$-3td %1$-9tB %1$tY";
public static void main(String[] args) {
Calendar c1 = new GregorianCalendar(2011, Calendar.FEBRUARY, 3);
Calendar c2 = new GregorianCalendar(2010, Calendar.MAY, 15);
Date today = new Date();
System.out.printf(FORMAT_STRING + "%n", c1);
System.out.printf(FORMAT_STRING + "%n", c2);
System.out.printf(FORMAT_STRING + "%n", today);
}
}