How to get next Friday 13th since the given LocalDate [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 11 months ago.
Improve this question
I need to get next Friday 13th since the given date using LocalDate.
How it could be implemented?

You can do it by using only methods plusMonths(), withDayOfMonth() of the LocalDate class.
The starting point is to adjust the day of the month of the given date to the target day 13. If the day of month of the given date is greater than 13, then the current date will be assigned to the 13th day of the next month, otherwise to the 13th day of the current month.
And then check in the loop whether the day of the week of the current date is Friday. Note that days of the week in java.util.time API are represented by enum DayOfWeek.
This approach allows to find the target date only withing a couple of iterations by skipping the whole month.
To avoid hard-coded values and make the code reusable, the day of the month and the day of the week are expected as parameters of the method getNextDay().
public static LocalDate getNextDay(LocalDate date, int dayOfMonth, DayOfWeek dayOfWeek) {
LocalDate current = date.getDayOfMonth() > dayOfMonth ?
date.plusMonths(1).withDayOfMonth(dayOfMonth) :
date.withDayOfMonth(dayOfMonth);
while (current.getDayOfWeek() != dayOfWeek) {
current = current.plusMonths(1);
}
return current;
}
public static void main(String[] args) {
System.out.println(getNextDay(LocalDate.now(), 13, DayOfWeek.FRIDAY));
System.out.println(getNextDay(LocalDate.now().plusMonths(5), 13, DayOfWeek.FRIDAY));
}
Output
2022-05-13 - from now ('2022-03-16')
2023-01-13 - from '2022-08-16'

You can do it by just adding 7 days to your LocalDate and you will get the expected day:
For example:
LocalDate today = LocalDate.now();
//tomorrow
LocalDate tomorrow = today.plusDays(1);
// next week day
LocalDate nextWeekDay= today.plusDays(7);
Or get it by this one :
today.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));

public static LocalDateTime nextFriday13() {
LocalDateTime now = LocalDateTime.now();
while (now.getDayOfMonth() != 13) {
now = now.plusDays(1);
}
while (!now.getDayOfWeek().equals(DayOfWeek.FRIDAY)) {
now = now.plusMonths(1);
}
return now;
}

First we look for the next Friday from the given date (getNextFriday). Then we check if she is 13 (is13Friday.)
public static void main(String[] args) {
boolean is13Friday = false;
LocalDate nextFriday = LocalDate.now();
while (!is13Friday) {
nextFriday = getNextFriday(nextFriday);
is13Friday = is13Friday(nextFriday);
}
System.out.println(nextFriday);
}
public static LocalDate getNextFriday(LocalDate d) {
return d.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
}
public static boolean is13Friday(LocalDate d) {
return d.getDayOfMonth() == 13;
}

You can use IntStream to iterate through days:
public static LocalDate findFridayThirteen(LocalDate fromDate) {
return IntStream.iterate(0, i -> i + 1)
.mapToObj(fromDate::plusDays)
.filter(date -> date.getDayOfWeek() == DayOfWeek.FRIDAY
&& date.getDayOfMonth() == 13)
.findFirst()
.orElseThrow();
}
Or, you can iterate only Fridays:
public static LocalDate findFridayThirteen(LocalDate fromDate) {
LocalDate nextFriday = fromDate.with(
TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY));
return IntStream.iterate(0, i -> i + 7)
.mapToObj(nextFriday::plusDays)
.filter(date -> date.getDayOfMonth() == 13)
.findFirst()
.orElseThrow();
}
Or, you can iterate only the 13 of each month:
public static LocalDate findFridayThirteen(LocalDate fromDate) {
LocalDate nextThirteen = fromDate.getDayOfMonth() > 13
? fromDate.withDayOfMonth(13).plusMonths(1)
: fromDate.withDayOfMonth(13);
return IntStream.iterate(0, i -> i + 1)
.mapToObj(nextThirteen::plusMonths)
.filter(date -> date.getDayOfWeek() == DayOfWeek.FRIDAY)
.findFirst()
.orElseThrow();
}
Test:
LocalDate date = LocalDate.of(2022, 1, 1);
LocalDate friday13 = findFridayThirteen(date);
DateTimeFormatter formatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.FULL);
System.out.println(friday13.format(formatter));
Output:
Friday, May 13, 2022

Related

Get start date and end date from week/month/year

I need to extract the start date and end date from a given year and week and return them as LocalDate:
Example: year / month / week : 2022 / 12 / 49 -> date_begin 05/12/2022 - date_end 11/12/2022 this mean the week 49 of the year 2022 starts from 05/12/2022 and ends on the 11/12/2022. The month is irrelevant, as #rzwitserloot said in the comments. The input is provided in ints int year = 2022 and int week = 49.
How to achieve this?
JSR310-extra had the YearWeek, but the somewhat simpler java.time does not - hence, the simplest way is through the parser even if you don't actually need to parse it:
int weekYear = 2022;
int weekNum = 49;
LocalDate monday = LocalDate.parse(String.format("%04d-W%02d-1", weekYear, weekNum), DateTimeFormatter.ISO_WEEK_DATE);
LocalDate sunday = monday.plusDays(6);
System.out.printf("Week %d of year %d runs from %s to %s\n", weekNum, weekYear, monday, sunday);
NB: The format is e.g. 2022-W49-1; the 1 is for 'monday'. Note that this is weekyears: That means the start date could be in the previous year (e.g. week 1 of certain years starts on december 30th in the previous year), or the end date could be in the next year. This is obvious if you think about it (weeks exist that start in one year and end in the next, and they have to be part of some year's 'week-year' system). Just thought I'd highlight it :)
This solution also works
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
public class Main {
public static final WeekFields US_WEEK_FIELDS = WeekFields.of(DayOfWeek.SUNDAY, 4);
public static void main(String[] args) {
LocalDate date1 = LocalDate.of(2022, 12, 29);
LocalDate date2 = LocalDate.now();
System.out.println(formatDate(date1));
System.out.println(formatDate(date2));
}
public static int getWeek(LocalDate date) {
return date.get(US_WEEK_FIELDS.weekOfWeekBasedYear());
}
public static int getMonth(LocalDate date) {
return date.getMonthValue();
}
public static int getYear(LocalDate date) {
return date.get(US_WEEK_FIELDS.weekBasedYear());
}
public static String formatDate(LocalDate date) {
int week = getWeek(date);
int month = getMonth(date);
int year = getYear(date);
return year + "/" + month + "/" + week;
}
}
When running I get in the console
2022/12/52
2022/12/49

LocalDateTime Java - Get same day of week for next month

I have a date and a time of a month, for example 31/01/2020 at 14:00:00, this is the last friday of January. How can I get the date for the last Friday of Feb, March, etc.? It should be dynamic because any date can come in, like the second Tuesday of any month and so on.
I am trying with the following with no luck:
LocalDateTime startTime = LocalDateTime.of(2020, 1, 31, 14, 0, 0);
final Calendar calendar = Calendar.getInstance();
calendar.set(startTime.getYear(), startTime.getMonthValue() - 1, startTime.getDayOfMonth(), startTime.getHour(), startTime.getMinute(), startTime.getSecond());
int ordinal = calendar.get(Calendar.WEEK_OF_MONTH);
startTime = startTime.plusMonths(1).with(TemporalAdjusters.dayOfWeekInMonth(ordinal, startTime.getDayOfWeek();
System.out.println(startTime);
it's printing 06/03/2020 (six of march) at 14:00:00 which is wrong and should be 28/02/2020
What am I missing?
Thanks!
As mentioned before, there is some ambiguity in which day of the week of the month you mean, that is, whether you mean the nth day of week or the last nth day of week of the month.
One such example is Monday, February 24th, 2020. It is the fourth and last Monday of February 2020. If you are going to try to determine this for March 2020, which Monday would you pick? The fourth Monday is 23 March, but the last Monday is 30 March.
So apparently, you'll need to distinguish between whether you count forward or backward.
You could, for instance, create a class which represents a certain day of week in a month. This holds three fields: a day-of-week, a position, and whether the position is backwards or not. E.g.
"The second Monday of the month" would have
dayOfWeek = DayOfWeek.MONDAY
position = 2
backwards = false
and
"The last Thursday of the month" would have
dayOfWeek = DayOfWeek.THURSDAY
position = 1
backwards = true
public class WeekdayInMonth {
private final boolean backwards;
private final DayOfWeek dayOfWeek;
private final int position;
private WeekdayInMonth(DayOfWeek dayOfWeek, int position, boolean backwards) {
if (position < 1 || position > 5) {
throw new DateTimeException("Position in month must be between 1 and 5 inclusive");
}
this.dayOfWeek = dayOfWeek;
this.position = position;
this.backwards = backwards;
}
}
We could add factory methods to create WeekdayInMonths from LocalDates:
public static WeekdayInMonth of(LocalDate date) {
int positionInMonth = (date.getDayOfMonth() - 1) / 7 + 1;
return new WeekdayInMonth(date.getDayOfWeek(), positionInMonth, false);
}
private static WeekdayInMonth ofReversing(LocalDate date) {
int lastDayOfMonth = date.with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
int positionInMonth = (lastDayOfMonth - date.getDayOfMonth()) / 7 + 1;
return new WeekdayInMonth(date.getDayOfWeek(), positionInMonth, true);
}
At last, we add a method to get a LocalDate from a YearMonth adjusted to the WeekdayInMonth.
public LocalDate toLocalDate(YearMonth yearMonth) {
// Get a temporal adjuster to adjust a LocalDate to match a day-of-the-week
TemporalAdjuster adjuster = this.backwards ? TemporalAdjusters.lastInMonth(this.dayOfWeek) : TemporalAdjusters.firstInMonth(this.dayOfWeek);
int weeks = this.position - 1;
LocalDate date = yearMonth.atDay(1)
.with(adjuster)
.plusWeeks(this.backwards ? 0 - weeks : weeks);
if (!Objects.equals(yearMonth, YearMonth.from(date))) {
throw new DateTimeException(String.format("%s #%s in %s does not exist", this.dayOfWeek, this.position, yearMonth));
}
return date;
}
Working example
Here a working example at Ideone.
Addendum
I am getting errors like this if the initial date is Jan 1 2020: java.time.DateTimeException: FRIDAY #5 in 2020-02 does not exist. How could I get the previous weekday in case this happens? In this case, how would I get the previous Friday?
Well, then you need to adjust your LocalDate so that it falls within the specified yearmonth. Since every month has at least four day-of-the-weeks and no more than five of them, the difference is never more than a week. We could, after removing the throw new DateTimeException line, simply adjust the returned LocalDate using plusWeeks.
I've forked the abovementioned example and added the toAdjustingLocalDate method.
This solution is kind of complicated but this is because "last of" or "third in" etc aren't always well defined and might not even exists under some conditions. So here is a solution that looks at the initial date and depending of the day of the month it either performs calculations from the start of the month, calculating forward, or the end of the month, calculating backwards.
From my testing it seems to generate the right results and I am sure some code refactoring could be done as well to improve the code but I leave that for the reader.
public static LocalDateTime nextWithSameDayOfMonth(LocalDateTime indate) {
if (indate.getDayOfMonth() < 15) {
return getForStartOfMonth(indate);
}
return getForEndOfMonth(indate);
}
private static LocalDateTime getForEndOfMonth(LocalDateTime indate) {
DayOfWeek dayOfWeek = indate.getDayOfWeek();
LocalDateTime workDate = indate.with(TemporalAdjusters.lastDayOfMonth());
int count = 0;
while (workDate.isAfter(indate)) {
count++;
workDate = workDate.minusWeeks(1);
}
LocalDateTime nextDate = indate.plusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
while (nextDate.getDayOfWeek() != dayOfWeek) {
nextDate = nextDate.minusDays(1);
}
return count == 0 ? nextDate : nextDate.minusWeeks(count - 1);
}
private static LocalDateTime getForStartOfMonth(LocalDateTime indate) {
DayOfWeek dayOfWeek = indate.getDayOfWeek();
LocalDateTime workDate = indate.with(TemporalAdjusters.firstDayOfMonth());
int count = 0;
while (workDate.isBefore(indate)) {
count++;
workDate = workDate.plusWeeks(1);
}
LocalDateTime nextDate = indate.plusMonths(1).with(TemporalAdjusters.firstDayOfMonth());
while (nextDate.getDayOfWeek() != dayOfWeek) {
nextDate = nextDate.plusDays(1);
}
return count == 0 ? nextDate : nextDate.plusWeeks(count - 1);
}
Could you check if the function work for you?
public class FindSameDayNextMonth {
public static void main(String[] args) {
System.out.println("Next month of 'today' is " + FindSameDayNextMonth.getSameDayNextMonth());
}
public static Date getSameDayNextMonth() {
LocalDateTime dt = LocalDateTime.now();
Calendar c = Calendar.getInstance();
c.set(Calendar.MONTH, dt.getMonthValue()-1);
c.set(Calendar.DAY_OF_MONTH, dt.getDayOfMonth());
c.add(Calendar.MONTH, 1);
return c.getTime();
}
}
The output is
Next month of today is Mon Sep 23 07:18:09 CDT 2019

Get start date of current financial year

Here in the UK, the tax year runs from 6 April to 5 April each year. I want to get the start date of the current tax year (as a LocalDate), so for example if today is 3 April 2020, then return 6 April 2019, and if today is 8 April 2020, then return 6 April 2020.
I can calculate it using some logic like the following:
date = a new LocalDate of 6 April with today's year
if (the date is after today) {
return date minus 1 year
} else {
return date
}
But is there some method I can use that is less complex and uses a more succinct, perhaps functional style?
There are a few different approaches, but it's easy enough to implement the logic you've already specified in a pretty functional style:
private static final MonthDay FINANCIAL_START = MonthDay.of(4, 6);
private static LocalDate getStartOfFinancialYear(LocalDate date) {
// Try "the same year as the date we've been given"
LocalDate candidate = date.with(FINANCIAL_START);
// If we haven't reached that yet, subtract a year. Otherwise, use it.
return candidate.isAfter(date) ? candidate.minusYears(1) : candidate;
}
That's pretty concise and simple. Note that it doesn't use the current date - it accepts a date instead. That makes it much easier to test. It's easy enough to call this and provide the current date, of course.
using java.util.Calendar, you can get financial year's START and END date in which your given date lies.
In India financial year starts from from 1 April and ends on 31st March,
for financial year 2020-21 , dates will be 1 April 2020
public static Date getFirstDateOfFinancialYear(Date dateToCheck) {
int year = getYear(dateToCheck);
Calendar cal = Calendar.getInstance();
cal.set(year, 3, 1); // 1 April of Year
Date firstAprilOfYear = cal.getTime();
if (dateToCheck.after(firstAprilOfYear)) {
return firstAprilOfYear;
} else {
cal.set(year - 1, 3, 1);
return cal.getTime();
}
}
In your case set cal.set(year, 0, 1); // 1 Jan of Year
public static Date getLastDateOfFinancialYear(Date dateToCheck) {
int year = getYear(dateToCheck);
Calendar cal = Calendar.getInstance();
cal.set(year, 2, 31); // 31 March of Year
Date thirtyFirstOfYear = cal.getTime();
if (dateToCheck.after(thirtyFirstOfYear)) {
cal.set(year + 1, 2, 31);
return cal.getTime();
} else {
return thirtyFirstOfYear;
}
}
In your case set cal.set(year, 11, 31); // 31 Dec of Year

Find the Day of week of a specific date when specified the first day of week [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am implementing a method similar to the VB Weekday function that can give the weekday number given any Day-of-Week as the start for the week.
For the example of "2010-02-16" (which is on a Tuesday), and a first-day-of-week of Sunday (1), I expect the value 3 as outcome.
This can be done with the help of Calendar class and little calculation.
Parse the Date
Get Calendar Instance and initialize it with parsed Date
Get the day of week number at that time
Calculate day of week w.r.t. startDay by doing the calculation pointed out by #Markus
Below method demonstrates that:
public int Weekday(String dateString, int startDay) {
Date date = null;
try {
SimpleDateFormat desiredFormat = new SimpleDateFormat("yyyy-MM-dd");
date = desiredFormat.parse(dateString);
} catch (ParseException e) {
e.printStackTrace();
return -1;
}
Calendar c = Calendar.getInstance();
c.setTime(date);
if (startDay == 0) {
return c.get(Calendar.DAY_OF_WEEK);
}
else {
return (((c.get(Calendar.DAY_OF_WEEK) - startDay + 7) % 7) + 1);
}
}
Update: Thanks to comment by #Markus
Summarizing the answers of JoD. and Asif Mujteba, that should be something like this:
import java.time.*;
import java.util.*;
public class SampleClass {
public static void main(String []args) throws Exception {
System.out.println(Weekday("2010-02-16", 1));
System.out.println(Weekday("2015-05-03", 1));
System.out.println(Weekday("2015-05-04", 1));
System.out.println(Weekday("2015-05-05", 1));
System.out.println(Weekday("2015-05-06", 1));
System.out.println(Weekday("2015-05-07", 1));
System.out.println(Weekday("2015-05-08", 1));
System.out.println(Weekday("2015-05-09", 1));
System.out.println(Weekday("2015-05-10", 1));
}
public static int Weekday(String dateString, int startDay) throws Exception {
LocalDate date = LocalDate.parse(dateString);
return (((date.getDayOfWeek().ordinal() - startDay + 2) % 7) + 1;
}
}
This will return:
3
1
2
3
4
5
6
7
1
And thats is the same as DateAndTime.Weekday returns ...
Below accepts the date provided as string, and formatted in the ISO-8601 extended local date format (e.g. 2010-02-16). The day of Week is using the DayOfWeek Enum. Note however that this depends on Java 8 (standard libraries, not Joda-Time). Use of LocalDate is important to avoid TimeZone and Time issues (partial days).
UPDATE: also provided a static method mimicking the VB version with an integer parameter for the date. All except 0 (System default based on NLS) are accepted.
UPDATE #2: Had to modify previous into previousOrSame otherwise we would get 8 instead of 1 as result. The result is expected to be in the range 1-7.
import java.time.DayOfWeek;
import java.time.LocalDate;
import static java.time.DayOfWeek.*;
import static java.time.temporal.ChronoUnit.*;
import static java.time.temporal.TemporalAdjusters.*;
public class Main {
public static void main(String[] args) {
// Thanks to #Markus for the testcase
System.out.println(getVbWeekday("2010-02-16", 1));
System.out.println(getVbWeekday("2015-05-03", 1));
System.out.println(getVbWeekday("2015-05-04", 1));
System.out.println(getVbWeekday("2015-05-05", 1));
System.out.println(getVbWeekday("2015-05-06", 1));
System.out.println(getVbWeekday("2015-05-07", 1));
System.out.println(getVbWeekday("2015-05-08", 1));
System.out.println(getVbWeekday("2015-05-09", 1));
System.out.println(getVbWeekday("2015-05-10", 1));
}
public static int getWeekdayNumber(String dateAsString,DayOfWeek firstDayOfWeek) {
LocalDate d = LocalDate.parse(dateAsString);
// add 1 because between is exclusive end date.
return (int)DAYS.between(d.with(previousOrSame(firstDayOfWeek)),d)+1;
}
public static int getVbWeekday(String dateAsString,int firstDayOfWeek) {
return getWeekdayNumber(dateAsString,SATURDAY.plus(firstDayOfWeek));
}
}
i have implemented below menitoned method in java using jodaTime which will return the difference.
public int generateDifference(String dtStr, int dayOfWeek) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
DateTime dt = formatter.parseDateTime(dtStr);
int day = dt.getDayOfWeek() + 1;
if (dayOfWeek < day) {
return 8 - Math.abs(dayOfWeek - day);
}
return 2 + Math.abs(dayOfWeek - day);
}

age calculation method doesnt return the correct age? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I calculate someone's age in Java?
I want to calculate the user age , and my method doesnt give the correct age in case if the month of birth is equal to the current month and the day of birth less than or equal the current day ( if the user enter his birth date through the date picker as 9/4/1990 or 4/4/1990 the age will be 21 not 22) how i can solve this problem ? what is the update i should do to get the correct age in this case ? please help me ....
this is my method
public static String getAge(int year,int month,int day) {
Calendar dob = Calendar.getInstance();
Calendar today = Calendar.getInstance();
dob.set(year, month, day);
int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
if (today.get(Calendar.DAY_OF_YEAR) < dob.get(Calendar.DAY_OF_YEAR)){
age--;
}
Integer ageInt = new Integer(age);
String ageS = ageInt.toString();
return ageS;
}
There are two problems with your code:
if the date of birth is 9th April 1990, you need to write dob.set(1990,3,9) as months start at 0 ==> you probably need dob.set(year, month - 1, day);
if the current year is a leap year and not the year of birth (or vice versa) and dates are after the 28/29 Feb, you will get 1 day difference on an identical date.
This seems to work but you should test it with various scenarios and make sure you are happy with the result:
public static String getAge(int year, int month, int day) {
Calendar dob = Calendar.getInstance();
Calendar today = Calendar.getInstance();
dob.set(year, month - 1, day);
int age = today.get(Calendar.YEAR) - dob.get(Calendar.YEAR);
if (today.get(Calendar.MONTH) < dob.get(Calendar.MONTH)) {
age--;
} else if(today.get(Calendar.MONTH) == dob.get(Calendar.MONTH)) {
if (today.get(Calendar.DAY_OF_MONTH) < dob.get(Calendar.DAY_OF_MONTH)) {
age--;
}
}
Integer ageInt = new Integer(age);
String ageS = ageInt.toString();
return ageS;
}
And a (very simplified) test:
public static void main(String[] args) { //today = 8 April 2012
System.out.println(getAge(1990,3,7)); //22
System.out.println(getAge(1990,3,8)); //22
System.out.println(getAge(1990,3,9)); //22
System.out.println(getAge(1990,4,7)); //22
System.out.println(getAge(1990,4,8)); //22
System.out.println(getAge(1990,4,9)); //21
System.out.println(getAge(1990,5,7)); //21
System.out.println(getAge(1990,5,8)); //21
System.out.println(getAge(1990,5,9)); //21
}
You can compute the difference by transforming both dates in milliseconds and than in a Date object for example. Code would be something like this:
long ageMilis = today.getTimeInMillis() - dob.getTimeInMillis();
Date age = new Date(ageMilis);
return age.toString();

Categories