Calendar add behaviour - java

Want to get first day of the next week (next monday), but call to getTime() changes the Calendar object.
Please tell me the right way to get first day of the next week.
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
public class Main {
public static void main(String[] args) {
{
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
final Calendar cal = new GregorianCalendar( 2013, 5, 6 );
cal.setFirstDayOfWeek( Calendar.MONDAY );
//System.out.println( sdf.format( cal.getTime() ) );
cal.set( Calendar.DAY_OF_WEEK, Calendar.MONDAY );
System.out.println( sdf.format( cal.getTime() ) ); // 2013-06-06
cal.add( Calendar.WEEK_OF_YEAR, 1 );
System.out.println( sdf.format( cal.getTime() ) ); // 2013-06-13
}
{
final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
final Calendar cal = new GregorianCalendar( 2013, 5, 6 );
cal.setFirstDayOfWeek( Calendar.MONDAY );
System.out.println( sdf.format( cal.getTime() ) ); // 2013-06-06
cal.set( Calendar.DAY_OF_WEEK, Calendar.MONDAY );
System.out.println( sdf.format( cal.getTime() ) ); // 2013-06-03
cal.add( Calendar.WEEK_OF_YEAR, 1 );
System.out.println( sdf.format( cal.getTime() ) ); // 2013-06-10
}
}
}

This is a nice example...
The Calendar is not easy to handle. You problem is the evaluation of the date.
The date of the Calendar is newly evaluated if you call e.g. getTime() or add().
In the second (correct) example you call getTime() after setting the first day of the week and the calendar is set to 2013-06-06. After that you change the day of the week and set the calendar new (via getTime()). Therefore it is now set to Monday.
In the first example you set the Calendar to the date and set the day of week. This leads to an invalid date (temporarily). 2013-06-06 is a Thursday and you set Monday. Now which one is the correct day of week? The Calendar implementation now chooses Thursday.
This is also well documented in the Javadoc. The section is named Calendar Fields Resolution.

Related

How to select sunday before first monday of the passed month

I want to select Sunday before first Monday of the passed month.
That Sunday may be in the same month or the previous month but I want date of Sunday. I tried below logic for getting Sunday, it works for the current month but if I try passing some another month like Nov-2017 then again I have to change MONDAY-2 to MONDAY-3. So this is not the correct way. So how can I achieve this ?
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println("Date " + c.getTime());
c.set(Calendar.DAY_OF_MONTH, Calendar.MONDAY - 2);
System.out.println("Date " + c.getTime());
I want to pass date to the code. So how can i do it ? like if I have date saved in variable then according to the input provided by that variable it should calculate the logic and provide the output
#Test
public void testDate() throws ParseException {
SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy");
Date d = fmt.parse("01-Nov-2017");
System.out.println(d);
Calendar c = Calendar.getInstance();
c.setTime(d);
getSundayBefore1thMondayOfMonth(c);
}
public void getSundayBefore1thMondayOfMonth(Calendar c) {
c.set(Calendar.DAY_OF_MONTH, 1);
int wd = c.get(Calendar.DAY_OF_WEEK);
if (wd > Calendar.MONDAY ) {
c.add(Calendar.DAY_OF_MONTH, 7);
}
c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println(c.getTime());
c.add(Calendar.DAY_OF_MONTH, -1);
System.out.println(c.getTime());
}
Wed Nov 01 00:00:00 CST 2017
Mon Nov 06 00:00:00 CST 2017
Sun Nov 05 00:00:00 CST 2017
If you are using Java 8, Then you can use java.time library and you can just use :
LocalDate firstMondayOfMonth = LocalDate.now().with(
TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)
);// This return 2018-01-01
LocalDate sunday = firstMondayOfMonth.minusDays(1);//This return 2017-12-31
To test with November 2017 you can use LocalDate.of instead LocalDate.now() like this :
LocalDate firstMondayOfMonth = LocalDate.of(2017, Month.NOVEMBER, 1).with(
TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)
);// This return 2017-11-06
LocalDate firstSunday = firstMondayOfMonth.minusDays(1);// This return 2017-11-05
tl;dr
YearMonth
.now() // Current year-month. Tip: Better to pass the optional time zone, as shown further down in this Answer.
.atDay( 1 ) // First of the current month.
.with( TemporalAdjusters.nextOrSame( DayOfWeek.MONDAY ) ) // Move from first day of month to the following Monday, or stay on the first if it already a Monday.
.minusDays( 1 ) // Move back one day from Monday to get a Sunday. May be in current month or in previous month.
java.time
You are using troublesome old date-date classes that are now legacy, supplanted by the java.time classes.
Determining the current month means determining the current date. Determining the current date requires a time zone. For any given moment, the date varies around the globe by zone.
ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
The YearMonth class represent the entire month.
YearMonth currentYearMonth = YearMonth.now( z ) ;
From that we can get the first of the month.
LocalDate firstOfMonth = currentYearMonth.atDay( 1 ) ;
We can move to a certain day of the week by calling on a TemporalAdjuster.
LocalDate firstMondayOfMonth = firstOfMonth.with( TemporalAdjusters.nextOrSame( DayOfWeek.MONDAY ) ) ;
LocalDate sundayBeforeFirstMondayOfMonth = firstMondayOfMonth.with( TemporalAdjusters.previous( DayOfWeek.SUNDAY ) ) ;
Logically, that last line could be replaced with .minusDays( 1 ) as we know the previous Sunday immediately precedes our Monday by definition.
In the code below, first we get the first monday in the month. Then we just subtract 1 day.
// input
int year = 2017;
int month = Calendar.NOVEMBER;
// get first monday of the month
Calendar c = Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
c.set(Calendar.MONTH, month);
c.set(Calendar.YEAR, year);
System.out.println("Date " + c.getTime());
// subtract 1
c.add(Calendar.DAY_OF_MONTH, -1);
System.out.println("Date " + c.getTime());
Try this:
Calendar calendar=Calendar.getInstance();
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
calendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
calendar.add(Calendar.DATE, -1);
System.out.println(calendar.getTime());
Calendar c = Calendar.getInstance();
c.setFirstDayOfWeek( Calendar.MONDAY); //Monday is first day of a week
c.setMinimalDaysInFirstWeek( 1); //first week of month is the week that has at least one day in this month
//c.setMinimalDaysInFirstWeek( 7); //first week of month must be a full week
c.set(Calendar.WEEK_OF_MONTH, 1); //move to first week of month
System.out.println("Date " + c.getTime());
c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); //move to Monday
System.out.println("Date " + c.getTime());
c.add( Calendar.DAY_OF_MONTH, -1); //go back one day
System.out.println("Date " + c.getTime());
Choose one of the c.setMinimalDaysInFirstWeek() method depending on what the first week of month means to you.
In Java 8, you can use the below code:
public static void getSundayBeforeFirstMondayOfMonth(LocalDate date){
date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).minusDays(1);
}
And, call the above method like below as per the requirement:
public static void callerMethod(){
// Call with Current Date
getSundayBeforeFirstMondayOfMonth(LocalDate.now());
//Call with Custom Date
LocalDate customDate = LocalDate.parse("27-11-2017", DateTimeFormatter.ofPattern("DD-MM-YYYY"));
getSundayBeforeFirstMondayOfMonth(customDate);
}

Calendar add method not working as expected

I want set a (Gregorian) Calendar time to start-of-day April 1, 2016. I do this by setting month, day and year, and then setting all the time fields to their minimum values, giving me:
04/01/2016 12:00:00:000
If I subtract one millisecond I expect to get the last millisecond on the previous day, but instead I get the last millisecond on the same day:
04/01/2016 11:59:59:999
(Note: I get similar results if I subtract one second, minute or hour.)
What am I missing? Sample code follows, thanks.
package com.scg.domain;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class AdHoc
{
private static final int[] UNUSED_CAL_FIELDS =
{
Calendar.HOUR,
Calendar.MINUTE,
Calendar.SECOND,
Calendar.MILLISECOND
};
public static void main(String[] args)
{
Calendar cal = getGoodDate( Calendar.APRIL, 1,2016 );
System.out.println( cal.getCalendarType() );
adjustTime( "present", cal, 0 );
adjustTime( "past", cal, -1 );
adjustTime( "future", cal, 1 );
}
private static void adjustTime( String comment, Calendar cal, int incr )
{
Calendar newCal = Calendar.getInstance();
newCal.setTime( cal.getTime() );
newCal.add( Calendar.MILLISECOND, incr );
SimpleDateFormat fmt =
new SimpleDateFormat( "MM/dd/YYYY HH:mm:ss:SSS" );
System.out.println( comment + ": " + fmt.format( newCal.getTime() ) );
}
private static Calendar getGoodDate( int month, int day, int year )
{
Calendar cal = Calendar.getInstance();
cal.set( Calendar.YEAR, year );
cal.set( Calendar.MONTH, month );
cal.set( Calendar.DAY_OF_MONTH, day );
for ( int field : UNUSED_CAL_FIELDS )
cal.set( field, cal.getMinimum( field ) );
return cal;
}
}
You've used Calendar.HOUR, which controls only the 1-12 hour, not the 0-23 hour. Because of this, even though getMinimum returns 0, it's interpreted as 12:00 in whichever of AM or PM cal already is in, which must be PM from getInstance() (returns "now"). You really have 12:00 noon (PM). When you subtract a millisecond, it's still the same day.
To set it to midnight, try Calendar.HOUR_OF_DAY, which controls the 0-23 hour.
With this change, I get the output:
gregory
present: 04/01/2016 00:00:00:000
past: 03/31/2016 23:59:59:999
future: 04/01/2016 00:00:00:001

Changing dates in weekly or monthly basis

I am working on Calendar project and I am wondering is there any build in function available in class Calendar in android which can change daily basis or weekly basis.
For e.g. I am storing a data in today's date. And I want to repeat that operation on daily basis or weekly basis.
I don't want to use Calendar api.
e.g.
let's say my Calendar instance variable storing date "2014-26-01"
so I want to do something like
final Calendar c = Calendar.getInstance();
for(int i = o ; i <= 30 ; i++){
yy = c.get(Calendar.YEAR);
mm = c.get(Calendar.MONTH);
dd = c.get(Calendar.DAY_OF_MONTH);
Toast.makeText(this,yy+"-"+mm+"-"+dd,Toast.LENGH_SHORT).show();
/** here i want to change the value of `Calendar c` to next day or next week**/
}
You can use the calendar.add() method to increase or decrease the date.
for example:
public void Calendar getTomorrow(){
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE,1);
//return the calendar with the date of tomorrow
return calendar;
}
public void Calendar getYesterday(){
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DATE,-1);
//return the calendar with the date of yesterday
return calendar;
}
By the way, the Joda-Time libary offers convenient plusDays, plusWeeks, and plusMonths methods for such calculations.
// java.util.Date dateNow = new java.util.Date();
// Convert a java.util.Date to Joda-Time. Simply pass Date to constructor.
// DateTime now = new DateTime( dateNow, DateTimeZone.forID( "Europe/Paris" ) );
DateTime now = new DateTime( DateTimeZone.forID( "Europe/Paris" ) );
DateTime tomorrow = now.plusDays( 1 );
DateTime nextWeek = now.plusWeeks( 1 );
DateTime firstMomentOfNextWeek = now.plusWeeks( 1 ).withTimeAtStartOfDay();
DateTime nextMonth = now.plusMonths( 1 );
// Convert from Joda-Time back to old outmoded bundled Java class, java.util.Date.
java.util.Date dateNow = now.toDate();
Dump to console…
System.out.println( "now: " + now );
System.out.println( "now in UTC/GMT: " + now.toDateTime( DateTimeZone.UTC ) );
System.out.println( "tomorrow: " + tomorrow );
System.out.println( "nextWeek: " + nextWeek );
System.out.println( "firstMomentOfNextWeek: " + firstMomentOfNextWeek );
System.out.println( "nextMonth: " + nextMonth );
System.out.println( "dateNow: " + dateNow ); // Remember, a j.u.Date lies. The `toString` applies default time zone, but actually a Date has no time zone.
When run…
now: 2014-01-27T00:06:41.982+01:00
now in UTC/GMT: 2014-01-26T23:06:41.982Z
tomorrow: 2014-01-28T00:06:41.982+01:00
nextWeek: 2014-02-03T00:06:41.982+01:00
firstMomentOfNextWeek: 2014-02-03T00:00:00.000+01:00
nextMonth: 2014-02-27T00:06:41.982+01:00
dateNow: Sun Jan 26 15:06:41 PST 2014

How to get name of the first day of a month?

How would I go about getting the first day of the month? So for January, of this year, it would return Sunday. And then for February it would return Wednesday.
To get the first date of the current month, use java.util.Calendar. First get an instance of it and set the field Calendar.DAY_OF_MONTH to the first date of the month. Since the first day of any month is 1, inplace of cal.getActualMinimum(Calendar.DAY_OF_MONTH), 1 can be used here.
private Date getFirstDateOfCurrentMonth() {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
return cal.getTime();
}
You can create a Calendar with whatever date you want and then do set(Calendar.DAY_OF_MONTH, 1) to get the first day of a month.
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DATE, 25);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.YEAR, 2012);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date firstDayOfMonth = cal.getTime();
DateFormat sdf = new SimpleDateFormat("EEEEEEEE");
System.out.println("First Day of Month: " + sdf.format(firstDayOfMonth));
public int getFirstDay(){
Calendar c=new GregorianCalendar();
c.set(Calendar.DAY_OF_MONTH, 1);
return c.get(Calendar.DAY_OF_WEEK);
}
From there you can see if the int is equal to Calendar.SUNDAY, Calendar.MONDAY, etc.
In the Java 8 you can use the TemporalAdjusters:
This is an example:
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
/**
* Dates in Java8
*
*/
public class App {
public static void main(String[] args) {
LocalDate localDate = LocalDate.now();
System.out.println("Day of Month: " + localDate.getDayOfMonth());
System.out.println("Month: " + localDate.getMonth());
System.out.println("Year: " + localDate.getYear());
System.out.printf("first day of Month: %s%n",
localDate.with(TemporalAdjusters.firstDayOfMonth()));
System.out.printf("first Monday of Month: %s%n", localDate
.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)));
System.out.printf("last day of Month: %s%n",
localDate.with(TemporalAdjusters.lastDayOfMonth()));
System.out.printf("first day of next Month: %s%n",
localDate.with(TemporalAdjusters.firstDayOfNextMonth()));
System.out.printf("first day of next Year: %s%n",
localDate.with(TemporalAdjusters.firstDayOfNextYear()));
System.out.printf("first day of Year: %s%n",
localDate.with(TemporalAdjusters.firstDayOfYear()));
LocalDate tomorrow = localDate.plusDays(1);
System.out.println("Day of Month: " + tomorrow.getDayOfMonth());
System.out.println("Month: " + tomorrow.getMonth());
System.out.println("Year: " + tomorrow.getYear());
}
}
The results would be:
Day of Month: 16
Month: MAY
Year: 2014
first day of Month: 2014-05-01
first Monday of Month: 2014-05-05
last day of Month: 2014-05-31
first day of next Month: 2014-06-01
first day of next Year: 2015-01-01
first day of Year: 2014-01-01
Last in Month Tuesday: 2014-05-27
Day of Month: 17
Month: MAY
Year: 2014
TemporalAdjuster
In java 8 you can use the new LocalDate and LocalTime API.
To achieve the coveted result, give a try to the following. It prints the name of the given day.
import java.time.*;
import java.time.temporal.*;
public class Main {
public static void main(String[] args) {
LocalDate l = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
System.out.println(l.getDayOfWeek());
}
}
Explanation:
now gives you the current date.
by calling with you can pass a TemporalAdjuster which are a key tool for modifying temporal objects.
getDayOfWeek Gets the day-of-week field, which is an enum DayOfWeek.
This includes textual names of the values.
TemporalAdjuster has a brother class, called TemporalAdjusters which contains static methods regarding the adjustments, like the one you are looking for, the firstDayOfMonth
Create java.util.Date or java.util.Calendar object, set date value and use java.text.SimpleDateFormat class method to format it.
Calendar cal=Calendar.getInstance();
cal.set(Calendar.DATE,1);
cal.set(Calendar.MONTH,0);
cal.set(Calendar.YEAR,2012);
SimpleDateFormat sdf=new SimpleDateFormat("EEEE");
System.out.println(sdf.format(cal.getTime()));
java.time
Since Java 8 we can also use YearMonth class which allows us to create LocalDate objects with specified days (first, last). Then We can simply convert these dates to DayOfWeek Enum (Tutorial) and read its name property.
YearMonth ym = YearMonth.of(2012, 1);
String firstDay = ym.atDay(1).getDayOfWeek().name();
String lastDay = ym.atEndOfMonth().getDayOfWeek().name();
System.out.println(firstDay);
System.out.println(lastDay);
result:
SUNDAY
TUESDAY
java.time, soft-coded
The Answer by Pshemo was good and clever, but is hard-coded to English. Let's take a stab at it allowing for localization.
ZoneId zoneId = ZoneId.of( "America/Montreal" ); // Time zone is crucial to determining a date.
YearMonth yearMonth = YearMonth.now( zoneId );
LocalDate firstOfMonth = yearMonth.atDay( 1 );
Formatter
Generate a textual representation of that LocalDate. We specify a desired Locale, in this case CANADA_FRENCH. If omitted, your JVM’s current default Locale is implicitly applied; better to specify explicit Locale.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "EEEE" ).withZone( zoneId ).withLocale( Locale.CANADA_FRENCH ); // Exactly four 'E' letters means full form. http://docs.oracle.com/javase/8/docs/api/java/time/format/TextStyle.html#FULL
String output = formatter.format( firstOfMonth );
Dump to console.
System.out.println( "output: " + output );
When run.
samedi
DayOfWeek Enum
Another route is to use the DayOfWeek enum. This enum includes a getDisplayName method where you specify both the text style (full name versus abbreviation) and a Locale.
DayOfWeek dayOfWeek = firstOfMonth.getDayOfWeek() ;
String output = dayOfWeek.getDisplayName( TextStyle.FULL_STANDALONE , Locale.CANADA_FRENCH ) ;
Simple and tricky answer
val calendar = Date()
val sdf = SimpleDateFormat("yyyy-MM-01 00:00:00", Locale.getDefault())
var result = sdf.format(calendar)
yyyy-MM-01 -> dd change to 01

Get first day of a particular week in Joda-Time? java

In Joda-Time, is there a way to get the date of the first day of the week(monday).
for instance i want to find out what date was this weeks monday based on todays current date 21/01/11
Cheers in advance.
edit: i also wish to find the date for the end of the week i.e sunday's date. cheers
Try LocalDate.withDayOfWeek:
LocalDate now = new LocalDate();
System.out.println(now.withDayOfWeek(DateTimeConstants.MONDAY)); //prints 2011-01-17
System.out.println(now.withDayOfWeek(DateTimeConstants.SUNDAY)); //prints 2011-01-23
LocalDate today = new LocalDate();
LocalDate weekStart = today.dayOfWeek().withMinimumValue();
LocalDate weekEnd = today.dayOfWeek().withMaximumValue();
Will give you the first and last days i.e Monday and sunday
Another option is to use roundFloorCopy. This looks like the following:
LocalDate startOfWeek = new LocalDate().weekOfWeekyear().roundFloorCopy();
For the last day of the standard week (Sunday) use roundCeilingCopy and minusDays…
LocalDate lastDateOfWeek = new LocalDate().weekOfWeekyear().roundCeilingCopy().minusDays( 1 );
Also works for DateTime. And works for end of week (exclusive).
DateTime dateTime = new DateTime();
DateTime startOfWeek = dateTime.weekOfWeekyear().roundFloorCopy();
DateTime endOfWeek = dateTime.weekOfWeekyear().roundCeilingCopy();
Dump to console…
System.out.println( "dateTime " + dateTime );
System.out.println( "startOfWeek " + startOfWeek );
System.out.println( "endOfWeek " + endOfWeek );
When run…
dateTime 2014-01-24T00:00:34.955-08:00
startOfWeek 2014-01-20T00:00:00.000-08:00
endOfWeek 2014-01-27T00:00:00.000-08:00
You can use the getDayOfWeek() method that gives you back 1 for Monday, 2 for Tue, .., 7 for Sunday in order to go back that many days and reach Monday:
import org.joda.time.DateTime;
public class JodaTest {
public static void main(String[] args) {
DateTime date = new DateTime();
System.out.println(date);
//2011-01-21T15:06:18.713Z
System.out.println(date.minusDays(date.getDayOfWeek()-1));
//2011-01-17T15:06:18.713Z
}
}
See the section "Querying DateTimes" of the Joda-Time user guide.
Here is the general algorithm I would follow:
find the day-of-week of the target date (Jan 21 2011 as you mentioned)
determine how many days ahead of Monday this is
Subtract the value of #2 from the target date using dateTime.minusDays(n)

Categories

Resources