Wrong last day of month - java

Where is some function to get the last day of month in my service?
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH);
Date date = format.parse(stringDate);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.MONTH, 1);
calendar.set(Calendar.DAY_OF_MONTH, 1);
calendar.add(Calendar.DATE, -1);
Date lastDayOfMonth = calendar.getTime();
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
return sdf.format(lastDayOfMonth);
So, this method correctly works elsewhere, but in US last day is always 29 (last day - 1)
stringDate is date in format "yyyy-MM-dd"

I believe this problem is due to Day Light saving time in US.
You can change this by setting the Timezone for Calendar to different timezone.
Related question: Adding days with java.util.Calendar gives strange results

Java Date has very poor API. Instead of this I would recommend you to use Joda Time.
In Joda it would look like this:
LocalDate endOfMonth = date.dayOfMonth().withMaximumValue();

If you don't have Java 8, this is very compact with JodaTime.
import org.joda.time.DateTime;
public class SoLastDay {
public DateTime lastDay(final String yyyy_MM_dd) {
DateTime givenDate = new DateTime(yyyy_MM_dd);
return givenDate.dayOfMonth().withMaximumValue();
}
}
And a small test...
#Test
public void testLastDay() throws Exception {
SoLastDay soLastDay = new SoLastDay();
String date1 = "2015-01-27";
System.out.printf("Date %s becomes %s.\n", date1, soLastDay.lastDay(date1).toString("yyyy-MM-dd"));
String date2 = "2015-02-02";
System.out.printf("Date %s becomes %s.\n", date2, soLastDay.lastDay(date2).toString("yyyy-MM-dd"));
}
And the test results:
Date 2015-01-27 becomes 2015-01-31.
Date 2015-02-02 becomes 2015-02-28.

If you do have Java 8, you might use code like this:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
public class SoLastDayJava8 {
static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public LocalDate lastDay(final String yyyy_MM_dd) {
LocalDate givenDate = LocalDate.parse(yyyy_MM_dd, formatter);
return givenDate.with(TemporalAdjusters.lastDayOfMonth());
}
}
The test code changes just a bit.
public class SoLastDayJava8Test {
#Test
public void testLastDay() throws Exception {
SoLastDayJava8 soLastDay = new SoLastDayJava8();
String date1 = "2015-01-27";
System.out.printf("Date %s becomes %s.\n", date1, soLastDay.lastDay(date1));
String date2 = "2015-02-02";
System.out.printf("Date %s becomes %s.\n", date2, soLastDay.lastDay(date2));
}
}
But the results are the same.
Date 2015-01-27 becomes 2015-01-31.
Date 2015-02-02 becomes 2015-02-28.

You are messing with the TimeZones.
When you execute Date date = format.parse(stringDate); you are creating a Date object with the TimeZone of the DateFormat object. Theoretically if the TimeZone is the same for all your DateFormat and Calendar objects, you should be fine. Check if they are coherent with the getTimeZone() method.
If the TimeZone of the first DateFormat is wrong (e.g. is your TimeZone or UTC or GMT), you'll get a UTC-008 conversion in the second TimeZone (and in the Calendar) resulting in the missing day since you start from midnight.
Judging from your code is the stringDate itself that has been wrongly converted somewhere else...

Related

Using Date instead of Timestamp

My code:
Calendar calendar = DateProvider.getCalendarInstance(TimeZone.getTimeZone("GMT"));
calendar.setTime(date);
calendar.set(Calendar.YEAR, 1970);
calendar.set(Calendar.MONTH, Calendar.JANUARY);
calendar.set(Calendar.DATE, 1);
date = calendar.getTime();
Timestamp epochTimeStamp = new Timestamp(date.getTime());
I want to eliminate the use of time stamp in this situation, how can achieve the same thing here with epochTimeStamp without using java.sql.Timestamp? I need the format to be same as if I was using Timestamp.
Since you need a String representation of your Date, then use SimpleDateFormat to convert the Date object into a String:
Calendar calendar = ...
//...
date = calendar.getTime();
Timestamp epochTimeStamp = new Timestamp(date.getTime());
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
try {
System.out.println(sdf.format(date));
System.out.println(sdf.format(epochTimeStamp));
} catch (Exception e) {
//handle it!
}
From your example, prints
01/01/1970 09:21:18
01/01/1970 09:21:18
This gives you the epoch time in the same format as TimeStamp:
public class FormatDate {
public static void main(String[] args) {
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd kk:mm:ss:SSS");
LocalDateTime datetime = LocalDateTime.of(1970, 1, 1, 0, 0);
System.out.println(datetime.format(format));
}
}
Another way to represent date time objects in Java is to use the Joda Time libraries.
import org.joda.time.LocalDate;
...
LocalDate startDate= new LocalDate();//"2014-05-06T10:59:45.618-06:00");
//or DateTime startDate = new DateTime ();// creates instance of current time
String formatted =
startDate.toDateTimeAtCurrentTime().toString("MM/dd/yyy HH:mm:ss");
There are several ways to do formatting, setting and getting Time using these libraries that has been more reliable than using the JDK Date and Calendar libraries. These will persist in hibernate/JPA as well. If nothing else, this hopefully gives you options.

Difference between date in miliseconds and its Calendar representation

I have two functions which convert a date String to a date in milliseconds:
public static long convertYYYYMMDDtoLong(String date) throws ParseException {
SimpleDateFormat f = new SimpleDateFormat("yyyy-mm-dd");
Date d = f.parse(date);
long milliseconds = d.getTime();
return milliseconds;
}
If I run this function I get the following result:
long timeStamp = convertYYYYMMDDtoLong("2014-02-17");
System.out.println(timeStamp);
It prints:
1389909720000
Now, if I run the following code:
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timeStamp);
System.out.println(cal.getTime());
It prints out:
Fri Jan 17 00:02:00 IST 2014
Why is my date shifted by one month? What is wrong?
P.S: My problem is that I need to map the date, represented as long, to another third party API which accepts Calendar format only.
You're using mm, which is minutes, not months. You want yyyy-MM-dd as your format string.
It's not clear why you're not returning a Calendar directly from your method, mind you:
private static final TimeZone UTC = TimeZone.getTimeZone("Etc/UTC")
public static Calendar convertYYYYMMDDtoCalendar(String text) throws ParseException {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
format.setTimeZone(UTC);
Calendar calendar = new GregorianCalendar(UTC);
calendar.setDate(format.parse(text));
return calendar;
}
(That's assuming you want a time zone of UTC... you'll need to decide that for yourself.)

Converting a Date to a new TimeZone in Java

Converting a Java Date object to a specific ("target") time zone is a question that has been asked numerous times before in StackOverflow and the suggested solutions apparently are:
Adjust the time (milliseconds) value of the Date object by the timezone offset
Use SimpleDateFormat (with the timezone) to produce the desired date as a String
However, there seems to be no "plain Java" solution that parses a date string (with or without timezone) into a Date object and then adjusts a corresponding Calendar object to the target timezone, so that the "converted" date behaves in all cases in the correct way (e.g., when using the Calendar object to retrieve the year of the date).
The main issue is that, reasonably, when the SimpleDateFormat pattern used to parse the date string does not have a timezone, the system assumes that the time is in the parsing system's timezone. If, however, the pattern does have a timezone, the time is counted from UTC. So, what is needed is essentially an indication as to whether the original date string corresponds to a pattern with or without a timezone, which apparently cannot be done without analyzing the pattern itself.
The attached source code of the TimezoneDate class demonstrates the discrepancies.
Here is the output from running the main() method for 2 "original dates", the first without and the second with a timezone, when they are converted to UTC on a machine running on Pacific Standard Time (PST):
Original date: 20/12/2012 08:12:24
Formatted date (TZ): 20/12/2012 16:12:24
Formatted date (no TZ): 20/12/2012 08:12:24
Calendar date: 20/12/2012 16:12:24
Expected date: 20/12/2012 08:12:24
Original date: 20/10/2012 08:12:24 +1200
Formatted date (TZ): 19/10/2012 20:12:24
Formatted date (no TZ): 19/10/2012 13:12:24
Calendar date: 19/10/2012 20:12:24
Expected date: 19/10/2012 20:12:24
The correct operation is to have the "Formatted" and "Calendar" strings identical to the "Expected date" for each of the 2 example date strings ("original dates").
Apparently one needs to make a distinction between the case where the date string contains a timezone symbol (TZ) and the case where it does not (no TZ), but this means knowing the SimpleDateFormat pattern beforehand, which is not possible when handling a Date object and not the original string.
So, the question is really about whether a generic "plain Java" (no third party libraries) solution exists that does not require prior knowledge of the pattern and works correctly with the corresponding Calendar object.
Following is the full source code of the TimezoneDate class.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class TimezoneDate
{
private final Date time;
private final TimeZone timezone;
private final Calendar calendar;
/**
* Creates a wrapper for a {#code Date} object that is converted to the
* specified time zone.
*
* #param date The date to wrap
* #param timezone The timezone to convert to
*/
public TimezoneDate(Date date, TimeZone timezone)
{
this.calendar = TimezoneDate.getPlainCalendar(date, timezone);
this.time = this.calendar.getTime();
this.timezone = timezone;
}
private static Calendar getPlainCalendar(Date date, TimeZone timezone)
{
Calendar calendar = Calendar.getInstance(timezone);
calendar.setTime(date);
return calendar;
}
private static Calendar getAdjustedCalendar(Date date, TimeZone timezone)
{
long time = date.getTime();
time = time + timezone.getOffset(time) - TimeZone.getDefault().getOffset(time);
date = new Date(time);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
return calendar;
}
public int getYear()
{
return this.calendar.get(Calendar.YEAR);
}
public int getMonth()
{
return (this.calendar.get(Calendar.MONTH)+1);
}
public int getMonthDay()
{
return this.calendar.get(Calendar.DAY_OF_MONTH);
}
public int getHour()
{
return this.calendar.get(Calendar.HOUR_OF_DAY);
}
public int getMinutes()
{
return this.calendar.get(Calendar.MINUTE);
}
public int getSeconds()
{
return this.calendar.get(Calendar.SECOND);
}
public String toCalendarDate() // The date as reported by the Calendar
{
StringBuilder sb = new StringBuilder();
sb.append(this.getMonthDay()).append("/").append(this.getMonth()).
append("/").append(this.getYear()).append(" ").
append(this.getHour()).append(":").append(this.getMinutes()).
append(":").append(this.getSeconds());
return sb.toString();
}
public String toFormattedDate(boolean addTimezone) // The formatted date string
{
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
if (addTimezone)
{
sdf.setTimeZone(this.timezone);
}
return sdf.format(this.time);
}
public static void main(String[] args) throws Exception
{
// Each data "vector" contains 3 strings, i.e.:
// - Original (example) date
// - SimpleDateFormat pattern
// - Expected date after converting the original date to UTC
String[][] data = new String[][]
{
{"20/12/2012 08:12:24", "dd/MM/yyyy' 'HH:mm:ss", "20/12/2012 08:12:24"},
{"20/10/2012 08:12:24 +1200", "dd/MM/yyyy HH:mm:ss Z", "19/10/2012 20:12:24"}
};
Date originalDate;
TimezoneDate timezoneDate;
SimpleDateFormat format;
TimeZone UTC = TimeZone.getTimeZone("UTC");
for (String[] vector:data)
{
format = new SimpleDateFormat(vector[1]);
originalDate = format.parse(vector[0]);
timezoneDate = new TimezoneDate(originalDate, UTC);
System.out.println();
System.out.println("Original date: " + vector[0]);
System.out.println("Formatted date (TZ): " + timezoneDate.toFormattedDate(true));
System.out.println("Formatted date (no TZ): " + timezoneDate.toFormattedDate(false));
System.out.println("Calendar date: " + timezoneDate.toCalendarDate());
System.out.println("Expected date: " + vector[2]);
}
}
}
Joda-Time
Rather than use Java's Date you should use the Joda-Time DateTime class. This allows you to carry out timezone operations in a very simple fashion, using the withTimezone() and withTimezoneRetainFields() methods depending on your particular requirements.

Calendar date to yyyy-MM-dd format in java

How to convert calendar date to yyyy-MM-dd format.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, 1);
Date date = cal.getTime();
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
String date1 = format1.format(date);
Date inActiveDate = null;
try {
inActiveDate = format1.parse(date1);
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
This will produce inActiveDate = Wed Sep 26 00:00:00 IST 2012. But what I need is 2012-09-26. My purpose is to compare this date with another date in my database using Hibernate criteria. So I need the date object in yyyy-MM-dd format.
A Java Date is a container for the number of milliseconds since January 1, 1970, 00:00:00 GMT.
When you use something like System.out.println(date), Java uses Date.toString() to print the contents.
The only way to change it is to override Date and provide your own implementation of Date.toString(). Now before you fire up your IDE and try this, I wouldn't; it will only complicate matters. You are better off formatting the date to the format you want to use (or display).
Java 8+
LocalDateTime ldt = LocalDateTime.now().plusDays(1);
DateTimeFormatter formmat1 = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.ENGLISH);
System.out.println(ldt);
// Output "2018-05-12T17:21:53.658"
String formatter = formmat1.format(ldt);
System.out.println(formatter);
// 2018-05-12
Prior to Java 8
You should be making use of the ThreeTen Backport
The following is maintained for historical purposes (as the original answer)
What you can do, is format the date.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, 1);
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
System.out.println(cal.getTime());
// Output "Wed Sep 26 14:23:28 EST 2012"
String formatted = format1.format(cal.getTime());
System.out.println(formatted);
// Output "2012-09-26"
System.out.println(format1.parse(formatted));
// Output "Wed Sep 26 00:00:00 EST 2012"
These are actually the same date, represented differently.
Your code is wrong. No point of parsing date and keep that as Date object.
You can format the calender date object when you want to display and keep that as a string.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, 1);
Date date = cal.getTime();
SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
String inActiveDate = null;
try {
inActiveDate = format1.format(date);
System.out.println(inActiveDate );
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
java.time
The answer by MadProgrammer is correct, especially the tip about Joda-Time. The successor to Joda-Time is now built into Java 8 as the new java.time package. Here's example code in Java 8.
When working with date-time (as opposed to local date), the time zone in critical. The day-of-month depends on the time zone. For example, the India time zone is +05:30 (five and a half hours ahead of UTC), while France is only one hour ahead. So a moment in a new day in India has one date while the same moment in France has “yesterday’s” date. Creating string output lacking any time zone or offset information is creating ambiguity. You asked for YYYY-MM-DD output so I provided, but I don't recommend it. Instead of ISO_LOCAL_DATE I would have used ISO_DATE to get this output: 2014-02-25+05:30
ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zonedDateTime = ZonedDateTime.now( zoneId );
DateTimeFormatter formatterOutput = DateTimeFormatter.ISO_LOCAL_DATE; // Caution: The "LOCAL" part means we are losing time zone information, creating ambiguity.
String output = formatterOutput.format( zonedDateTime );
Dump to console…
System.out.println( "zonedDateTime: " + zonedDateTime );
System.out.println( "output: " + output );
When run…
zonedDateTime: 2014-02-25T14:22:20.919+05:30[Asia/Kolkata]
output: 2014-02-25
Joda-Time
Similar code using the Joda-Time library, the precursor to java.time.
DateTimeZone zone = new DateTimeZone( "Asia/Kolkata" );
DateTime dateTime = DateTime.now( zone );
DateTimeFormatter formatter = ISODateTimeFormat.date();
String output = formatter.print( dateTime );
ISO 8601
By the way, that format of your input string is a standard format, one of several handy date-time string formats defined by ISO 8601.
Both Joda-Time and java.time use ISO 8601 formats by default when parsing and generating string representations of various date-time values.
java.util.Date object can't represent date in custom format instead you've to use SimpleDateFormat.format method that returns string.
String myString=format1.format(date);
public static void main(String[] args) {
Calendar cal = Calendar.getInstance();
cal.set(year, month, date);
SimpleDateFormat format1 = new SimpleDateFormat("yyyy MM dd");
String formatted = format1.format(cal.getTime());
System.out.println(formatted);
}
In order to parse a java.util.Date object you have to convert it to String first using your own format.
inActiveDate = format1.parse( format1.format(date) );
But I believe you are being redundant here.
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DATE, 7);
Date date = c.getTime();
SimpleDateFormat ft = new SimpleDateFormat("MM-dd-YYYY");
JOptionPane.showMessageDialog(null, ft.format(date));
This will display your date + 7 days in month, day and year format in a JOption window pane.
public static String ThisWeekStartDate(WebDriver driver) {
Calendar c = Calendar.getInstance();
//ensure the method works within current month
c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
System.out.println("Before Start Date " + c.getTime());
Date date = c.getTime();
SimpleDateFormat dfDate = new SimpleDateFormat("dd MMM yyyy hh.mm a");
String CurrentDate = dfDate.format(date);
System.out.println("Start Date " + CurrentDate);
return CurrentDate;
}
public static String ThisWeekEndDate(WebDriver driver) {
Calendar c = Calendar.getInstance();
//ensure the method works within current month
c.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
System.out.println("Before End Date " + c.getTime());
Date date = c.getTime();
SimpleDateFormat dfDate = new SimpleDateFormat("dd MMM yyyy hh.mm a");
String CurrentDate = dfDate.format(date);
System.out.println("End Date " + CurrentDate);
return CurrentDate;
}
I found this code where date is compared in a format to compare with date field in database...may be this might be helpful to you...
When you convert the string to date using simpledateformat, it is hard to compare with the Date field in mysql databases.
So convert the java string date in the format using select STR_to_DATE('yourdate','%m/%d/%Y') --> in this format, then you will get the exact date format of mysql date field.
http://javainfinite.com/java/java-convert-string-to-date-and-compare/
My answer is for kotlin language.
You can use SimpleDateFormat to achieve the result:
val date = Date(timeInSec)
val formattedDate = SimpleDateFormat("yyyy-MM-dd", Locale("IN")).format(date)
for details click here.
OR
Use Calendar to do it for you:
val dateObject = Date(timeInMillis)
val calendarInstance = Calendar.getInstance()
calendarInstance.time = dateObject
val date = "${calendarInstance.get(Calendar.YEAR)}-${calendarInstance.get(Calendar.MONTH)}-${calendarInstance.get(Calendar.DATE)}"
For more details check this answer.
I don't know about y'all, but I always want this stuff as a one-liner. The other answers are fine and dandy and work great, but here is it condensed to a single line. Now you can hold less lines of code in your mind :-).
Here is the one Liner:
String currentDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

How do I parse a date where I only have the day name?

Given a String that is simply a day, for example, "Thu" or "Thursday", how would I get a java.util.Calendar object where the day String represents the closest String to today. In other words, today is Monday, 3/26/29012, so if the String were "Thu", I would want to form a date that represents "3/29/2012". If the String passed in is "Mon" and we're on Monday, I would want today's date. In this example, "3/26/2012".
I tried this ...
final DateFormat formatter = new SimpleDateFormat("EEE");
java.util.Date date = (Date) formatter.parse(dayOfWeekStr);
final Calendar now = Calendar.getInstance();
dateCal.set(Calendar.YEAR, now.get(Calendar.YEAR));
dateCal.set(Calendar.MONTH, now.get(Calendar.MONTH));
dateCal.setTime(date);
but it isn't working. Once I set the date, the year and month results to 1970, January.
You are almost there. Just put .setTime(..) ontop of the rest. Currently you are overriding your YEAR and MONTH changes by setting the time.
As Kevin noted, it might not work in all cases. For that reason I'd suggest you use a different approach: get only the DAY_OF_WEEK from a calendar, based on the parsed date, and set it to now. Of course, you should take care of changing the week if you need to.
I ended up going with
public static Calendar getNearestDateFromDayString(final String dayOfWeekStr,
final Calendar startingDay) throws ParseException {
final DateFormat formatter = new SimpleDateFormat("EEE");
final java.util.Date date = (Date) formatter.parse(dayOfWeekStr);
final Calendar result = Calendar.getInstance();
result.setTime(date);
result.set(Calendar.YEAR, startingDay.get(Calendar.YEAR));
result.set(Calendar.MONTH, startingDay.get(Calendar.MONTH));
result.set(Calendar.HOUR, startingDay.get(Calendar.HOUR));
result.set(Calendar.MINUTE, startingDay.get(Calendar.MINUTE));
result.set(Calendar.SECOND, 0);
java.util.Date today = new java.util.Date();
while (result.getTimeInMillis() <= today.getTime()) {
result.add(Calendar.DATE, 7);
} // while
return result;
} // getNearestDateFromDayString
If anyone has a more concise solution, I'll accept that instead.

Categories

Resources