Good day all,
I was trying to create a date variable by using Calendar java, the following is my example code:
long day = System.currentTimeMillis();
Calendar cal = Calendar.getInstance();
java.text.SimpleDateFormat month = new java.text.SimpleDateFormat("MMM"); // not sure how to assign this value inside
cal.setTimeInMillis(day);
cal.set(Calendar.HOUR_OF_DAY, 00);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
cal.set(Calendar.MILLISECOND, 000);
Date todayDate = cal.getTime();
Timestamp current = new Timestamp(todayDate.getTime());
However, the value of current I get is 2014-01-13 00:00:00.0. I prefer to set the 01 to Jan instead.
Any ideas on this?
You mean something like so?
long day = System.currentTimeMillis();
Calendar cal = Calendar.getInstance();
java.text.SimpleDateFormat month = new java.text.SimpleDateFormat("yyyy-MMM-dd HH:mm:ss:S"); // not sure how to assign this value inside
cal.setTimeInMillis(day);
cal.set(Calendar.HOUR_OF_DAY, 00);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
cal.set(Calendar.MILLISECOND, 000);
Date todayDate = cal.getTime();
Timestamp current = new Timestamp(todayDate.getTime());
System.out.println(month.format(current));
Yields:
2014-Jan-13 00:00:00:0
Please check the SimpleDateFormat for more formatting options.
You can try this
long day = System.currentTimeMillis();
Calendar cal = Calendar.getInstance();
SimpleDateFormat month = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss:S");
cal.setTimeInMillis(day);
cal.set(Calendar.HOUR_OF_DAY, 00);
cal.set(Calendar.MINUTE, 00);
cal.set(Calendar.SECOND, 00);
cal.set(Calendar.MILLISECOND, 000);
Date todayDate = cal.getTime();
Timestamp current = new Timestamp(todayDate.getTime());
System.out.println(month.format(current));
Now out put:
2014-Jan-13 00:00:00:0
ideone
// not sure how to assign this value inside
there you go.. ;)
yy = year (2 digit)
yyyy = year (4 digit)
M = month of the year
MM = month of the year (leading 0)
MMM = month of the year (short text)
MMMM = month of the year (full text)
d = day of the month
dd = day of the month (leading 0)
h = hour (1-12)
H = hour (0-23)
m = minute of the hour
s = second of the minute
S = milisecond
E = day of the week (short)
EEEE = day of the week (full)
D = day of the Year
Additional link to the SimpleDateFormat class
Since you are looking for current date, you do not need currentTimeMillis().
Instead you can do the following to get the desired output.
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 sdf = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss.S");
System.out.println(sdf.format(cal.getTime()));
tl;dr
Avoid the troublesome legacy date-time classes. Use only java.time classes.
LocalDate.now() // Determine the current date as seen in the wall-clock time in use by JVM’s current default time zone. Better to specify explicitly your desired/expected time zone.
.getMonth() // Get the `Month` enum object representing the month of that `LocalDate` object’s date value.
.getDisplayName( // Let the `Month` enum object automatically localize to generate the string of the name of the month.
TextStyle.SHORT , // Specify how long or abbreviate you want the text of the name of the month.
Locale.US // Specify a `Locale` to determine the human language and cultural norms to be used in localizing the name of the month.
) // Return a String.
Jan
java.time
The modern approach uses java.time classes.
Getting the current month means determining the current date. And getting the current date requires a time zone, as for any given moment the date varies around the globe by zone.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate ld = LocalDate.now( z ) ;
Month m = ld.getMonth();
Let the Month enum automatically localize the name of the month. Control abbreviation by passing a TextStyle.
String output = m.getDisplayName( TextStyle.SHORT , Locale.US );
Apr
Date with time
If your goal is to combine a time-of-day with your date, use ZonedDateTime class. You must specify a time zone to determine the first moment of the day. The day does not start at 00:00:00 on some dates in some zones.
ZonedDateTime zdt = ld.atStartOfDay( z ) ; // Determine the first moment of the day.
Do not use java.sql.Timestamp for the purpose of generating a String. Use the DateTimeFormatter class, documented in many other Answers on Stack Overflow.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MMM-dd HH:mm:ss" , Locale.US ) ;
String output = zdt.format( f ) ;
Or just call ZonedDateTime::toString to generate a String in standard ISO 8601 format, wisely extended to append the name of the zone in square brackets.
String output = zdt.toString() ;
Indeed, do not use Timestamp at all. That class is intended for use with databases, and is now replaced by Instant as of JDBC 4.2 and later.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Related
I need to use calendar to do this approach, basicly i get the specific day of week (1,2,3) each int represents a day of week(Monday,Tuesday) not in this order, but the logic is this.
What i need is to get the date of the next day of week, imagine today is Monday, and the user select Wednsesday, i need to get the date of the next Wednesday.
My logic is this at the moment:
calendar.set(Calendar.DAY_OF_WEEK, dayOfWeek);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
dateMatch = calendar.getTime();
day of week is passed from a slidePicker, and represents the specific day of week, this DAY_OF_WEEK doesn't work, if i put Wednseday he gives me 6
Although your question text only says to find next dayOfWeek, your code also includes a time of day, in the form of hour and minute.
Assuming you want the first future occurrence of that combination, i.e. dayOfWeek, hour, and minute, that means that if today is that dayOfWeek, you either want today if time of day is later than now, or next week if time of day is earlier than now.
You can do that like this:
int dayOfWeek = Calendar.WEDNESDAY;
int hour = 10; // 10 AM
int minute = 0;
Calendar cal = Calendar.getInstance(); // Today, now
if (cal.get(Calendar.DAY_OF_WEEK) != dayOfWeek) {
cal.add(Calendar.DAY_OF_MONTH, (dayOfWeek + 7 - cal.get(Calendar.DAY_OF_WEEK)) % 7);
} else {
int minOfDay = cal.get(Calendar.HOUR_OF_DAY) * 60 + cal.get(Calendar.MINUTE);
if (minOfDay >= hour * 60 + minute)
cal.add(Calendar.DAY_OF_MONTH, 7); // Bump to next week
}
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
System.out.println(cal.getTime()); // Prints: Wed May 10 10:00:00 EDT 2017
tl;dr
To get the next Wednesday after today, or stick with today’s date if already a Wednesday.
LocalDate.now( ZoneId.of( "Africa/Tunis" ) )
.with( TemporalAdjusters.nextOrSame( DayOfWeek.WEDNESDAY ) )
java.time
Use modern java.time classes that supplanted the troublesome old legacy date-time classes such as Calendar.
Use DayOfWeek enum objects to represent Monday-Sunday. Use smart objects rather than dumb integers to represent your day-of-week intention. Makes your code more self-documenting, ensures valid values, and provides type-safety.
The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
Use a TemporalAdjuster implementation such as TemporalAdjusters.nextOrSame to move to another date.
TemporalAdjuster ta = TemporalAdjusters.nextOrSame( DayOfWeek.WEDNESDAY ) ;
LocalDate nextOrSameWednesday = today.with( ta ) ;
If working with moments, use ZonedDateTime class rather than the awful Calendar class. Some idea as above, let the TemporalAdjuster do the heavy-lifting. But keep in mind that the time-of-day may be altered if that time-of-day is invalid for that new date such as during a Daylight Saving Time (DST) cut-over.
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
TemporalAdjuster ta = TemporalAdjusters.nextOrSame( DayOfWeek.WEDNESDAY ) ;
ZonedDateTime zdtSameOrNextWednesday = zdt.with( ta ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Please read question carefully before marking duplicate.
I want previous date of a corresponding date.(Not yesterday's date)
e.g. If user click button once he will be navigated to another screen and is shown data regarding yesterday.
And if he clicks again the same button on that screen, then data should be shown on day before yesterday....and so on... till data present in my database.
So I want to get previous date of a corresponding date. i.e. if I have date 31 Jan 2014(I'm using format 31012014 to store in db) then i should get date 30012014.
I know how to get yesterday's date e.g. below code
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, -1);
DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy", Locale.getDefault());
String yesterdayAsString = dateFormat.format(calendar.getTime());
which gives dates compared to today but I want previous date compared to some other valid date.
So how to get that.
You have to use SimpleDateFormat to convert String > Date, after Date > Calendar, for instance;
String sDate = "31012014";
SimpleDateFormat dateFormat = new SimpleDateFormat("ddMMyyyy", Locale.getDefault());
Date date = dateFormat.parse(sDate);
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DATE, -1);
String yesterdayAsString = dateFormat.format(calendar.getTime());
Use this, Its working and tested code.
private String getPreviousDate(String inputDate){
inputDate = "15-12-2015"; // for example
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");
try {
Date date = format.parse(inputDate);
Calendar c = Calendar.getInstance();
c.setTime(date);
c.add(Calendar.DATE, -1);
inputDate = format.format(c.getTime());
Log.d("asd", "selected date : "+inputDate);
System.out.println(date);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
inputDate ="";
}
return inputDate;
}
tl;dr
Use modern java.time classes. Repeatedly subtract a day to move backwards in time.
LocalDate // Represent a date-only value, without time-of-day and without time zone.
.now( // Determine the current date as perceived in the wall-clock time used by the people of a particular region (a time zone).
ZoneId.of( "Europe/Paris" ) // Use real time zone names in `Continent/Region` format, never 2-4 letter pseudo-zones such as PST, EST, IST, CEST, etc.
) // Returns a `LocalDate` object.
.minusDays( 1 ) // Move back in time by one day, for yesterday’s date. Returns another separate `LocalDate` object rather than modify the original, per Immutable Objects pattern.
.minusDays( 1 ) // Continue moving back in time another day.
.minus(
Period.ofDays( 1 ) // Define a span-of-time as any number of years-months-weeks-days.
) // Continuing to subtract yet another day.
.toString() // Generate text representing that last generated `LocalDate` date-value using standard ISO 8601 format.
When parsing your text inputs.
LocalDate
.parse(
"30012014" ,
DateTimeFormatter.ofPattern( "ddMMuuuu" )
)
.minusDay( 1 )
.minus(
Period.ofDays( 1 )
)
java.time
The modern approach uses the java.time classes that years ago supplanted the troublesome old date-time classes.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Date math
Your Question is not clear, but it seems you simply want to increment backwards in time one day at a time. This is quite easy with the LocalDate class offering plus & minus methods.
Call the convenience method, LocalDate::minusDays.
LocalDate yesterday = LocalDate.now( ZoneId.of( "Africa/Tunis" ) ).minusDays( 1 ) ;
To move backwards, subtract again.
LocalDate localDatePrior = yesterday.minusDays( 1 ) ;
And continue onwards.
localDatePrior = localDatePrior.minusDays( 1 ) ;
You can soft-code the period of time to subtract using the Period class with the LocalDate.minus method.
Period p = Period.ofDays( 1 ) ;
LocalDate localDatePrior = yesterday.minus( p ) ;
Database
(I'm using format 31012014 to store in db)
Don’t.
To store a date-only value in your database, use a date-only type in your column. In a SQL-compliant database, the type will be DATE for a date-only value.
As of JDBC 4.2 we can directly exchange java.time objects with the database.
myPreparedStatement.setObject( … , localDate ) ;
Retrieval.
LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;
Parsing
But to directly address your current situation, you can parse your string with its peculiar format of DDMMYYYY.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "ddMMuuuu" ) ;
LocalDate localDate = LocalDate.parse( "30012014" , f ) ;
String output = localDate.toString() ; // Generate text in standard ISO 8601 format.
By the way, rather than invent your own date-time format, always use standard ISO 8601 formats when exchanging date-time values as text. The java.time classes wisely use these formats by default when parsing/generating strings.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
Try this one
String prevDate;
Date c = Calendar.getInstance().getTime();
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yyyy");
String todayDate=df.format(c);
Date date = null;
try {
date = df.parse(todayDate);
} catch (ParseException e) {
e.printStackTrace();
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.add(Calendar.DATE, -1);
prevDate = df.format(calendar.getTime());
Test=(TextView)findViewById(R.id.test);
Test.setText(prevDate);
You've got everything right, except before you "add" -1 days, you need to set it to the date you want (before finding the previous date previous):
Calendar calendar = Calendar.getInstance();
calendar.set(2014, Calendar.JUNE, 9);
calendar.add(Calendar.DATE, -1);
...
First off just as a tip, it is better to store your dates as timestamps like so you won't be dependent on time formats.
As for your question, just keep your current date in a variable and send it to your method once the button is clicked and then subtract an extra day
Calendar curDate = Calendar.getInstance();
curDate.add(Calendar.DATE, -1);
and use your curDate variable from then on
Try this:
final Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE, -1);
String yesterdayAsString = fmtOut.format(calendar.getTime());
long calendar=Calendar.getInstance().getTimeInMillis()-1000*60*60*24;
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy");
String date = sdf.format(calendar);
So I have a string which is "2014-06-30 15:27" and if it is today's date it should only return "15:27" else "30/06/2014". I've already tried simpleDateFormat.parse but it didn't work very well.
holder.data.setText(mensagem.getDate());
final String stringDate = "2014-07-17 23:59";
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
Date date = inputFormat.parse(stringDate);
Calendar calendarDate = Calendar.getInstance();
calendarDate.setTime(date);
Calendar midnight = Calendar.getInstance();
midnight.set(Calendar.HOUR_OF_DAY, 0);
midnight.set(Calendar.MINUTE, 0);
midnight.set(Calendar.SECOND, 0);
midnight.set(Calendar.MILLISECOND, 0);
if (calendarDate.compareTo(midnight) >= 0)
{
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
System.out.println(timeFormat.format(date));
}
else
{
SimpleDateFormat dateTimeForm = new SimpleDateFormat("dd/MM/yyyy HH:mm");
System.out.println(dateTimeForm.format(date));
}
LocalDateTime
First parse the string as a LocalDateTime. Replace the SPACE in the middle with T to comply with standard ISO 8601 format. The java.time classes support ISO 8601 formats by default.
LocalDateTime ldt = LocalDateTime.parse ( "2014-06-30 15:27".replace ( " " , "T" ) );
ldt.toString(): 2014-06-30T15:27
Such a value has no real meaning. The input string lacked any clue about offset-from-UTC or time zone. So we do not know if this is 3 PM in Auckland NZ or 3 PM in Québec Canada, two very different moments. You should to assign the offset or time zone indicated by your business situation. Search Stack Overflow for how to do this, focussing on classes OffsetDateTime and ZonedDateTime. I'll skip over this crucial issue for now.
LocalDate
Extract a date-only value. The LocalDate class represents a date-only value without time-of-day and without time zone.
LocalDate ld = ldt.toLocalDate();
Today
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
Comparison
You can compare LocalDate objects by calling methods such as compareTo, equals, isEqual, isBefore, isAfter.
if( today.isEqual( ld ) ) {
return ldt.toLocalTime();
} else {
return ld;
}
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
As the java.time library is the recommended way to use date and time. So, to compare current date with a string date you need to first convert date in string format to java.time.LocalDate :
LocalDate paresedStringDate = LocalDate.parse("2022-11-10");
After that you can get the current date using below code:
LocalDate currentDate = LocalDate.now();
And then you can compare both the current date and parsed string date to check if both are same using below code:
if (paresedStringDate.compareTo(currentDate) == 0) {
//do what you want to do here
}
Simply use the Date class...
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
Date exitdate = df.parse("2019-01-17");
Date currdate = new Date();
long diff = currdate.getTime() - exitdate.getTime();
long days = TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
if(days==0)
{
System.out.println("IS TRUE"+currdate.toString());
return true;
}
I'd like to parse string in MM-dd format to java date. Since year is not specified, parsed date should be in current year. Only valid date string should be parsed, so I should use setLenient(false) in SimpleDateFormat.
public static Date parseDate(String ds) throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("MM-dd");
df.setLenient(false);
Date d = df.parse(ds);
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
cal.setTime(d);
cal.set(Calendar.YEAR, year);
return cal.getTime();
}
This seems to work well until I pass an argument "02-29". This year(2012) is leap year and 2012-02-29 is valid date, "02-29" should have been parsed successfully.
I found that when I don't specify year part in SimpleDateFormat, it parse to year 1970. And 1970 is not a leap year, "02-29" fails to parse. So, parsing to date of year 1970 and set current year after parsing strategy is not perfect.
What is the best way to parse MM-dd format string to date (date should be set to current year) in Java?
PS1: I searched this topic and found many questions and answers in this site, but I couldn't find the satisfactory answer.
PS2: df.setLenient(false); is important because only valid date string should be parsed successfully. Invalid date strings like "01-32", "02-30", etc. shouldn't be parsed.
Thanks in advance.
tl;dr
parse string in MM-dd format … in current year
MonthDay // Represent a month-day as such, in a class designed for that purpose.
.parse ( // By default parses strings in standard ISO 8601 format.
"--" + "02-29" // Prepending a double-hyphen to make this input comply with ISO 8601.
) // Returns a `MonthDay` object.
.atYear( // Get the date of this month-day in a specified year.
Year.now( ZoneId.of( "Asia/Tokyo" ) ).getValue() // Getting current year requires a time zone.
) // Returns a `LocalDate` object, a year-month-day without time zone and without time-of-day.
See this code run live at IdeOne.com.
2019-02-28
java.time
The modern solution uses the industry-leading java.time classes built into Java 8 and later, with a back-port available for Java 6 & 7 and early Android.
MonthDay
A month-with-day is represented by the appropriately-named MonthDay class.
The standard format for a month-day defined in ISO 8601 is a --MM-DD where the first dash is a placeholder for year. The ISO 8601 formats are used by default in the java.time classes for parsing/generating strings.
Your input nearly complies. You could define a formatting pattern with a DateTimeFormatter object. But I would just prepend a -- onto the input.
String input = "02-29" ;
String inputModified = "--" + input ;
And then parse by default.
MonthDay md = MonthDay.parse( inputModified ) ;
See this code run live at IdeOne.com.
md.toString(): --02-29
Leap year
Note that your leap year problem goes away. By use an appropriate type that truly represents a month-and-day instead of a moment, we need not worry about leap year.
To get a date for this month-day, simply call MonthDay::atYear to obtain a LocalDate object. Pass a year number.
LocalDate leapYear2012 = md.atYear( 2012 ) ;
leapYear2012.toString(): 2012-02-29
Current year
Getting a date in the current year has a twist that may be surprising to you. Note that getting the current year requires getting the current date. And getting the current date requires a time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If you want to use the JVM’s current default time zone, make your intention clear by calling ZoneId.systemDefault(). If critical, confirm the zone with your user.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
In our case, we care only about the year. So we can use the Year class rather than LocalDate. But same idea with the time zone. If the current moment happens to be around New Years Eve/Day cutover, the year will vary around the globe by time zone.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
Year y = Year.now( z ) ;
LocalDate currentYear = md.atYear( y.getValue() ) ;
currentYear.toString(): 2019-02-28
Notice in the result above that leap year is handled automatically. There is no February 29th in 2019, so java.time adjusted to the 28th.
Parse as LocalDate
Alternatively, you could parse directly into a LocalDate. You would need to use the DateTimeFormatterBuilder class to build a DateTimeFormatter that defaults to a certain year.
Something like this:
ZoneId zKolkata = ZoneId.of( "Asia/Kolkata" ) ;
long yearNumber = Year.now( zKolkata ).getValue() ;
DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseDefaulting( ChronoField.YEAR , yearNumber ).appendPattern( "MM-dd").toFormatter() ;
LocalDate ld = LocalDate.parse( "02-28" , formatter ) ;
System.out.println( "ld.toString(): " + ld ) ;
But I do not recommend this. The approach with MonthDay object is much more clear as to your problem, solution, and intention. Another benefit: if you are getting such inputs, I suspect you will likely need to be working with the month-day as such, and with MonthDay class you have an object at hand to do the job.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
This could be considered a little hacky, but you could always just tack the year onto the end of the date string before parsing, like this:
ds += "-" + Calendar.getInstance().get(Calendar.YEAR);
SimpleDateFormat df = new SimpleDateFormat("MM-dd-yyyy");
// Parse date as usual
Get the year from the calendar as you do in the code, set the parse format string to MM-dd-yyyy and then do
Date d = df.parse(ds + "-" + year);
If you know your Strings are in the correct format, the other answers about appending the current year should suffice.
If your need is to handle input strings of unknown formats (you are unsure if the year is on the String or not), you can first attempt to parse the Date using the full format, then fall back on the shorter format with an override for the year.
public static Date parseDate(String ds) throws ParseException {
SimpleDateFormat fullFormat = new SimpleDateFormat("MM-dd-yyyy");
fullFormat.setLenient(false);
try {
return fullFormat.parse(ds);
} catch (ParseException e) {}
// Full format unsuccessful. Attempt short format.
SimpleDateFormat shortFormat = new SimpleDateFormat("MM-dd");
shortFormat.setLenient(false);
Date d = shortFormat.parse(ds);
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
cal.setTime(d);
cal.set(Calendar.YEAR, year);
return cal.getTime();
}
Bonus: If you want a "catch-all" parser for some reason, define a bunch of non-lenient date formats and check them one by one. Note that order matters; the first to match will return. If you want to set the default year, you'll have to take it a step further and check if the default 1970 year is somehow referred in the input:
public static Date parseDate(String ds) throws ParseException {
Calendar cal = Calendar.getInstance();
int currentYear = cal.get(Calendar.YEAR);
for (DateFormat knownFormat : knownFormats) {
try {
Date d = knownFormat.parse(ds);
cal.setTime(d);
if (cal.get(Calendar.YEAR) == 1970 && !ds.contains("70")) {
cal.set(Calendar.YEAR, currentYear);
}
return cal.getTime();
} catch (ParseException e) {}
}
throw new ParseException("Unknown date format for String: " + ds);
}
I have a class Movie
in it i have a start Date, a duration and a stop Date.
Start and stop Date are Date Objects (private Date startDate ...)
(It's an assignment so i cant change that)
now I want to automatically calculate the stopDate by adding the duration (in min) to the startDate.
By my knowledge working with the time manipulating functions of Date is deprecated hence bad practice but on the other side i see no way to convert the Date object to a calendar object in order to manipulate the time and reconvert it to a Date object.
Is there a way? And if there is what would be best practice
What you could do is creating an instance of a GregorianCalendar and then set the Date as a start time:
Date date;
Calendar myCal = new GregorianCalendar();
myCal.setTime(date);
However, another approach is to not use Date at all. You could use an approach like this:
private Calendar startTime;
private long duration;
private long startNanos; //Nano-second precision, could be less precise
...
this.startTime = Calendar.getInstance();
this.duration = 0;
this.startNanos = System.nanoTime();
public void setEndTime() {
this.duration = System.nanoTime() - this.startNanos;
}
public Calendar getStartTime() {
return this.startTime;
}
public long getDuration() {
return this.duration;
}
In this way you can access both the start time and get the duration from start to stop. The precision is up to you of course.
Calendar tCalendar = Calendar.getInstance();
tCalendar.setTime(date);
date is a java.util.Date object. You may use Calendar.getInstance() as well to obtain the Calendar instance(much more efficient).
Calendar.setTime()
It's often useful to look at the signature and description of API methods, not just their name :) - Even in the Java standard API, names can sometimes be misleading.
You don't need to convert to Calendar for this, you can just use getTime()/setTime() instead.
getTime():
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this Date object.
setTime(long time) : Sets this Date object to represent a point in time that is time milliseconds after January 1, 1970 00:00:00 GMT. )
There are 1000 milliseconds in a second, and 60 seconds in a minute. Just do the math.
Date now = new Date();
Date oneMinuteInFuture = new Date(now.getTime() + 1000L * 60);
System.out.println(now);
System.out.println(oneMinuteInFuture);
The L suffix in 1000 signifies that it's a long literal; these calculations usually overflows int easily.
tl;dr
Instant stop =
myUtilDateStart.toInstant()
.plus( Duration.ofMinutes( x ) )
;
java.time
Other Answers are correct, especially the Answer by Borgwardt. But those Answers use outmoded legacy classes.
The original date-time classes bundled with Java have been supplanted with java.time classes. Perform your business logic in java.time types. Convert to the old types only where needed to work with old code not yet updated to handle java.time types.
If your Calendar is actually a GregorianCalendar you can convert to a ZonedDateTime. Find new methods added to the old classes to facilitate conversion to/from java.time types.
if( myUtilCalendar instanceof GregorianCalendar ) {
GregorianCalendar gregCal = (GregorianCalendar) myUtilCalendar; // Downcasting from the interface to the concrete class.
ZonedDateTime zdt = gregCal.toZonedDateTime(); // Create `ZonedDateTime` with same time zone info found in the `GregorianCalendar`
end if
If your Calendar is not a Gregorian, call toInstant to get an Instant object. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = myCal.toInstant();
Similarly, if starting with a java.util.Date object, convert to an Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = myUtilDate.toInstant();
Apply a time zone to get a ZonedDateTime.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
To get a java.util.Date object, go through the Instant.
java.util.Date utilDate = java.util.Date.from( zdt.toInstant() );
For more discussion of converting between the legacy date-time types and java.time, and a nifty diagram, see my Answer to another Question.
Duration
Represent the span of time as a Duration object. Your input for the duration is a number of minutes as mentioned in the Question.
Duration d = Duration.ofMinutes( yourMinutesGoHere );
You can add that to the start to determine the stop.
Instant stop = startInstant.plus( d );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to java.time.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8 and SE 9 and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
something like
movie.setStopDate(movie.getStartDate() + movie.getDurationInMinutes()* 60000);
Here is a full example on how to transform your date in different types:
Date date = Calendar.getInstance().getTime();
// Display a date in day, month, year format
DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
String today = formatter.format(date);
System.out.println("Today : " + today);
// Display date with day name in a short format
formatter = new SimpleDateFormat("EEE, dd/MM/yyyy");
today = formatter.format(date);
System.out.println("Today : " + today);
// Display date with a short day and month name
formatter = new SimpleDateFormat("EEE, dd MMM yyyy");
today = formatter.format(date);
System.out.println("Today : " + today);
// Formatting date with full day and month name and show time up to
// milliseconds with AM/PM
formatter = new SimpleDateFormat("EEEE, dd MMMM yyyy, hh:mm:ss.SSS a");
today = formatter.format(date);
System.out.println("Today : " + today);
Extension for converting date to calendar in Kotlin.
fun Date?.toCalendar(): Calendar? {
return this?.let { date ->
val calendar = Calendar.getInstance()
calendar.time = date
calendar
}
}