Strange java.util.calendar Output - java

I am trying to clear the time portion from a Date using Java Calendar. Here is the code based on the other stackoverflow solutions:
Calendar cal = Calendar.getInstance();
// cal.setTime(new Date());
cal.clear(Calendar.HOUR);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
// cal.clear(Calendar.ZONE_OFFSET);
cal.clear(Calendar.HOUR_OF_DAY);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
dateFormat.format(cal.getTime());
System.out.println(dateFormat.format(cal.getTime()));
System.out.println(cal.getTime());
But the current output is: 2014-01-20 12:00:00
What could be the reason? Why the time is showing 12:00:00? I just want my Date Object with a time 00:00:00.

The date/calendar is ok, the error is in your format string:
hh: means 12h time format
HH: means 24h time format
Correct format string:
yyyy-MM-dd HH:mm:ss
Output:
2014-01-20 00:00:00
Mon Jan 20 00:00:00 CET 2014

As per javadoc of Calendar.clear:
The HOUR_OF_DAY, HOUR and AM_PM fields are handled independently and
the the resolution rule for the time of day is applied. Clearing one
of the fields doesn't reset the hour of day value of this Calendar.
Use set(Calendar.HOUR_OF_DAY, 0) to reset the hour value.
So instead of clear use:
cal.set(Calendar.HOUR_OF_DAY, 0)
clear isn't actually clearing hour value, hence so much messing around formatters!

Do like this
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
dateFormat.format(cal.getTime());
System.out.println(dateFormat.format(cal.getTime()));
System.out.println(cal.getTime());

Related

Why does a date conversion return different timestamps?

I am converting a GregorianCalendar instance to a Date to get a unix timestamp.
But I was wondering why the same date returns different Unix timestamps each time.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar = new GregorianCalendar();
calendar.set(2018, 0, 1, 0,0,0);
System.out.println(sdf.format(calendar.getTime()));
Date date = calendar.getTime();
System.out.println(sdf.format(date));
System.out.println(date.getTime());
The date itself is correct and is always the same, "2018/01/01 00:00:00". But why is the unix timestamp different each time? For example, these are the values after 5 executions.
1514761200624
1514761200618
1514761200797
1514761200209
1514761200132
When you create a new calendar it contains current date and time. After that you update all fields EXCEPT milliseconds. As you can see only last 3 numbers differs in all your outputs, it is milliseconds of the execution time.
java.time
ZoneId zone = ZoneId.of("Europe/Brussels");
ZonedDateTime start2018 = LocalDate.of(2018, Month.JANUARY, 1).atStartOfDay(zone);
Instant asInstant = start2018.toInstant();
System.out.println(asInstant.toEpochMilli());
This consistently gives the following output:
1514761200000
Please substitute your desired time zone if it didn’t happen to be Europe/Brussels.
To format for output:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
System.out.println(start2018.format(formatter));
2018/01/01 00:00:00
The date and time classes that you were using — SimpleDateFormat, Calendar, GregorianCalendar and Date — are all poorly designed and long outdated. SimpleDateFormat in particular is notoriously troublesome, but in this case it was the poor design of Calendar that gave you unexpected results. The other answers have already explained how, there is no need for me to repeat. Instead of the old classes I recommend that you use java.time, the modern Java date and time API. It is so much nicer to work with.
Link: Oracle tutorial: Date Time explaining how to use java.time.
In timestamp, last 3-digit represents the milliseconds. Here you are explicitly setting the date and time but not the milliseconds. That's why you are facing this. To avoid this you can add this to your code:
calendar.set(Calendar.MILLISECOND, 0);
I am assuming you are instantiating everything within a loop in your example?
If so, you are not setting the milliseconds difference, so they change (however slightly) in each iteration of the loop.
To avoid this, you could either set the milliseconds, or do the instantiation outside of the loop:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Calendar calendar = new GregorianCalendar();
calendar.set(2018, 0, 1, 0, 0, 0);
for (int i = 0; i < 5; i++) {
System.out.println(sdf.format(calendar.getTime()));
Date date = calendar.getTime();
System.out.println(sdf.format(date));
System.out.println(date.getTime());
}
This will produce:
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128
2018/01/01 00:00:00
2018/01/01 00:00:00
1514764800128

How to set datetime to end of day in java

I want to set datetime of day as: startDate=2018/03/28 00:00:00 and endDate=2018/03/28 23:59:59
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
String str1=sdf1.format(cal.getTime());
String str2=sdf2.format(cal.getTime());
Date startDate = sdf1.parse(str1);
Date endDate = sdf2.parse(str2);
My problem:program is working and output endDate=2018/03/28 00:00:00
Would you please point out any mistakes to me in code?
update:
i used debug and it's working correct with
String str2=sdf2.format(cal.getTime());//2018-03-28 23:59:59
but when change string==>date is not correct with output 2018/03/28 00:00:00
If you want to initialize Date instances from a formatted string with both date and time then time codes should be added to the SimpleDateFormat pattern to parse strings in that format.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date startDate = sdf.parse("2018-03-28 00:00:00");
Date endDate = sdf.parse("2018-03-28 23:59:59");
If you want to simply set the hour, minute, and second on the current date then use a Calendar instance and set fields on it accordingly.
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0)
Date startDate = cal.getTime();
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999)
Date endDate = cal.getTime();
And next output the Date in a particular format:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
System.out.println(sdf.format(startDate));
System.out.println(sdf.format(endDate));
Output:
2018/03/28 00:00:00
2018/03/28 23:59:59
Dealing with time zones
If time zone is other than the local time zone then it's a good idea to be explicit with what timezone you're working with. Calendar and SimpleDateFormat instances must be consistent with what timezone you're dealing with or the date and/or times may be off.
TimeZone utc = TimeZone.getTimeZone("UTC");
Calendar cal = Calendar.getInstance(utc);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
sdf.setTimeZone(utc);
A substitute for SimpleDateFormat is using DateTimeFormatter class found in the newer java.time package added to Java 8.
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str1=sdf1.format(cal.getTime());
String str2=sdf2.format(cal.getTime());
try {
Date startDate = sdf3.parse(str1);
Date endDate = sdf3.parse(str2);
System.out.println(str1);
System.out.println(str2);
System.out.println(startDate.toString());
System.out.println(endDate.toString());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
OUT PUT
2018-03-28 00:00:00
2018-03-28 23:59:59
Wed Mar 28 00:00:00 ICT 2018
Wed Mar 28 23:59:59 ICT 2018
I think, maybe sdf1 and sdf2 don't provide clear format.
So change time to HH:mm:ss.
If you just want to get the Date values for today's start and end times, you don't need to use date formatting utilities (like SimpleDateFormat) at all:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
Date startDate = cal.getTime();
cal.set(Calendar.HOUR_OF_DAY, 23);
cal.set(Calendar.MINUTE, 59);
cal.set(Calendar.SECOND, 59);
cal.set(Calendar.MILLISECOND, 999);
Date endDate = cal.getTime();
You can solve this problem like this
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd 23:59:59");
String str1=sdf1.format(cal.getTime());
String str2=sdf2.format(cal.getTime());
Date startDate = sdf1.parse(str1);
Date endDate = sdf2.parse(str2);
String startDateTime = sdf1.format(startDate);
String endDateTime = sdf2.format(endDate);
System.out.println("startDate ----->" + startDateTime);
System.out.println("endDate ----->" + endDateTime);
The output of this
startDate ----->2018-03-28 00:00:00
endDate ----->2018-03-28 23:59:59
Hope this is what you want.

Date object that gets the current date, but with a time i control which can be converted to unix time

I want to be able to request java to get the current date, then I would like to control the time added to that date object and then convert that date object to unix time.
i.e. something like
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, 0);
today.set(Calendar.MINUTE, 0);
today.set(Calendar.SECOND, 0);
today.set(Calendar.MILLISECOND, 0);
Then do this using the Calendar object as a converted string
String dateString = "Fri, 09 Nov 2012 23:40:18 GMT"; //but this
DateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy
hh:mm:ssz");
Date date = dateFormat.parse(dateString );
long unixTime = (long) date.getTime()/1000;
System.out.println(unixTime );
Any help would be appreciated.
First of all, there are some issues with your date format: You have to use capital H for hours when parsing 24-hour times, and I think there was a space missing in front of the timezone z.
Using the newer Java time API, you can try this:
ZonedDateTime.parse("Fri, 09 Nov 2012 23:40:18 GMT", DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss z"))
.with(LocalDate.now())
.toEpochSecond();
The new API is very strict when it come to timezones, you might want to watch out for that. In this implementation, the parsed time defines the timezone (GMT in this example). But maybe you want your local timezone (defined by the virtual machine)? In this case, you can turn it around: ZonedDateTime.now().with(ZonedDateTime.parse(...).toLocalTime()).
In your original approach, why do you not continue with the Calendar?
Date parsedDate = ...;
Calendar today = Calendar.getInstance();
today.set(Calendar.HOUR_OF_DAY, parsedDate.getHours());
today.set(Calendar.MINUTE, parsedDate.getMinutes());
today.set(Calendar.SECOND, parsedDate.getSeconds());
today.set(Calendar.MILLISECOND, 0);
long epoch = today.getTimeInMillis() / 1000;
But again, beware of timezones.

set time to 00:00:00 doesn't work - java

I want to set string that contain the new current date and the time 00:00:00.
I wrote the following code but time is set to 12:00:00
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
String today1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").
format(calendar.getTime())
I'd love to know why the code does not work or, alternatively, get another method to set time to 00:00:00
You've used the format characters hh, which is the 12-hour, or am/pm, based hour scheme.
h Hour in am/pm (1-12) Number 12
You've printed 12:00 am without the "am". The time of day is set to midnight, but with your format "yyyy-MM-dd hh:mm:ss" the output is confusing at best.
You can do either of the following:
Switch to capital "H" characters to switch to a 24-hour clock as per your requirements:
H Hour in day (0-23) Number 0
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
Output:
2016-02-18 00:00:00
Or you can add the "a" format character to add the am/pm designation.
a Am/pm marker Text PM
new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a")
Output:
2016-02-18 12:00:00 AM

Convert SAS date value to Java YYYY-MM-DD

I have SAS date objects stored as integer and they look like : 19725.
I am trying to write java code to convert the date to YYYY-MM-DD
I see in the documentation that the SAS date value is the number of days from 01 Jan 1960
For example:
02 Jan 1960 would return 1
04 June 2003 would return 15680
Could you give the java code for this conversion. ie. convert something like 19725 to the date format : YYYY-MM-DD
I try the logic below but 15680 gives 2003-01-06 and not 2003-06-04 as the output. Could anyone point the mistake.Thanks in advance.
int numdays = 15680;
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.MONTH, 1);
cal.set(Calendar.YEAR, 1960);
cal.add(Calendar.DAY_OF_MONTH, numdays);
String strdate = null;
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-DD");
if (cal != null) {
strdate = sdf.format(cal.getTime());
}
System.out.println(strdate);
Month are 0-based, so you're setting your calendar to February, not January. This should fix the issue:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.MONTH, Calendar.JANUARY);
// ...
In addition to RC's point about starting the month correctly with Calendar.JANUARY, your simpledateformat is wrong.
SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
'DD' is day of year (so 340th day of the year is Dec 6). 'dd' is day of the month. See the doc for more detail. (Also note that 15680 is Dec 6 2002, not what you say in the question.)
You may actually want to use 'yy' also:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
as 'YYYY' is "Week Year", which in some cases may differ from yyyy (calendar year) near the end of the year. See the docs for more details.
I like to use JodaTime for date manipulation like this.
http://www.joda.org/joda-time/apidocs/org/joda/time/DateTime.html#plusDays-int-
int sasDate = 19725;
DateTime base = new DateTime(1960, 1, 1, 0, 0);
DateTime computed = base.plusDays(sasDate);

Categories

Resources