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

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

Related

Random date generation in Java that is any date 26 days ago from today

I want to write a code wherein I can generate a random date between 26 days ago from today's date. That is, if today's date is 12th April, I wanted my code to generate any date from 17th of March to 12th of April means 17th April is 26 days ago from 12th April.
How to write this in Java? Can anyone help?
package apiActions;
import java.time.LocalDate;
public class RandomDates {
public static void main(String[] args) {
//for (int i = 0; i < 10; i++) {
LocalDate randomDate = createRandomDate(2022, 2022);
System.out.println(randomDate);
System.out.println(randomDate.minusDays(26));
// }
}
public static int createRandomIntBetween(int start, int end) {
return start + (int) Math.round(Math.random() * (end - start));
}
public static LocalDate createRandomDate(int startYear, int endYear) {
int day = createRandomIntBetween(1, 31);
int month = createRandomIntBetween(1, 4);
int year = createRandomIntBetween(startYear, endYear);
return LocalDate.of(year, month, day);
}
}
Tried this but I am not getting how to modify. Also I want date in the format yyyy-mm-dd.
Get today’s date. Subtract a random number of days. Call toString to generate text in standard ISO 8601 format of YYYY-MM-DD.
LocalDate
.now() // Better to specify explicitly your desired time zone. If omitted, the JVM’s current default time zone is implicitly applied.
.minusDays(
ThreadLocalRandom
.current()
.nextLong( 0 , 27 ) // ( inclusive , exclusive ). So 0,27 for 0 through 26.
) // Returns another `LocalDate` object.
.toString() // Generates text in standard ISO 8601 format.
See this code run live at IdeOne.com.
2022-03-31
Well, here is one way. Just get the current day and subtract 0 to 26 days.
Random r= new Random();
LocalDate ldt = LocalDate.now().minusDays(r.nextLong(27));
System.out.println(ldt);
Prints something like
2022-04-11

How to get next Friday 13th since the given LocalDate [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 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

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

Java - Generate Random DOB [duplicate]

This question already has answers here:
How can I pad an integer with zeros on the left?
(18 answers)
Adding zero to a single digit number, Is it possible?
(2 answers)
Generate random date of birth
(15 answers)
Closed 5 years ago.
I want to generate random DOB for the given range of year. So I tried the below code
private static String randomDataOfBirth(int yearStart, int yearEnd)
{
GregorianCalendar gc = new GregorianCalendar();
int year = randBetween(yearStart, yearEnd);
gc.set(Calendar.YEAR, year);
int dayOfYear = randBetween(1, gc.getActualMaximum(Calendar.DAY_OF_YEAR));
gc.set(Calendar.DAY_OF_YEAR, dayOfYear);
String date = null;
if(gc.get(Calendar.MONTH) == 0)
{
date = gc.get(Calendar.YEAR) + "-" + 1 + "-" + gc.get(Calendar.DAY_OF_MONTH);
}else
{
date = gc.get(Calendar.YEAR) + "-" + gc.get(Calendar.MONTH) + "-" + gc.get(Calendar.DAY_OF_MONTH);
}
return date;
}
private static int randBetween(int start, int end) {
// TODO Auto-generated method stub
return start + (int)Math.round(Math.random() * (end - start));
}
Main:-
public static void main(String[] args) {
String dob = randomDataOfBirth(1899, 1937);
System.out.println(dob);
}
I can be able to generate the random DOB. But only for the Month and Day, I want to add a prefix '0' for the range from 1 to 9
Month - 01, 02, 03 and ... up to 09
Day - 01, 02, 03 and ... up to 09
Apart from the desired formatting of you date I see some other problems with your code that I think you would want to address:
Assuming you want a usual month number, 01 for January through 12 for December, your handling of the month number is not correct. get(Calendar.MONTH) gives you a 0-based month: 0 for January through 11 for December. Therefore, your code not only will never give you 12 as month and 1 all too often. It will also give you non-existing dates. I have seen 1905-2-31 and 1929-4-31 (because you get 2 for March, which we interpret as February, etc.).
Possibly unimportant, your distribution gives each day in a leap year slightly smaller probablity than other days.
If you can, I suggest you use LocalDate. The class was introduced in Java 8:
private static String randomDataOfBirth(int yearStartInclusive, int yearEndExclusive) {
LocalDate start = LocalDate.ofYearDay(yearStartInclusive, 1);
LocalDate end = LocalDate.ofYearDay(yearEndExclusive, 1);
long longDays = ChronoUnit.DAYS.between(start, end);
int days = (int) longDays;
if (days != longDays) {
throw new IllegalStateException("int overflow; too many years");
}
int day = randBetween(0, days);
LocalDate dateOfBirth = start.plusDays(day);
return dateOfBirth.toString();
}
This gives you evenly distributed, correct dates formatted with 2 digits for month and day-of-month, e.g., 1926-07-05.
If you want to avoid the overflow check, you may of course rewrite your randBetween() to handle longs.
If you cannot use Java 8, you can do something similar with GregorianCalendar and SimpleDateFormat. Counting the exact number of days from lower to upper bound is complicated, though, so you will probably want to stick to your way of picking the date. SimpleDateFormat can still give you correct dates formatted with two digits for month and day. Edit: In your class, declare:
static DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Now just substitute your if-else statement with this:
String date = formatter.format(gc.getTime());
If your randomDataOfBirth() may be accessed from more than one thread, this won’t work since SimpleDateFormat is not thread-safe. If so, each thread should have its own SimpleDateFormat instance.
With Java7 you can try with something like this:
public class DobMaker
{
public String getDOB(int min, int max)
{
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
int year = min + new Random().nextInt(max - min + 1);
calendar.set(Calendar.YEAR, year);
int day = 1+new Random().nextInt(calendar.getActualMaximum(Calendar.DAY_OF_YEAR));
calendar.set(Calendar.DAY_OF_YEAR, day);
return new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
}
public static void main(String[] args)
{
DobMaker d = new DobMaker();
System.out.println(d.getDOB(1970, 1980));
System.out.println(d.getDOB(1970, 1971));
System.out.println(d.getDOB(2007, 2016));
}
}

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