I am getting week number and year from DB(using function DATE_PART('week',alarm_date - (interval '1 days') * 0) AS week, DATE_PART('year',alarm_date) AS yearNo , ISO compliant) and on the basis of week number and year i want to calculate weekStartDate and weekEndDate between user provided startdate and end date with week start date for example {"startDate":"2021-12-28","endDate":"2022-01-06","weekStartDay":"Sunday"}
private String getWeek(LocalDate startTime, LocalDate endTime, int yearNo, int weekNumber, int weekStartDay){
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Calendar cal = Calendar.getInstance();
// make it ISO compliant since postgres is using ISO time to calculate week number
cal.setMinimalDaysInFirstWeek(4);
cal.set(Calendar.YEAR, yearNo);
cal.set(Calendar.WEEK_OF_YEAR, weekNumber);
//ISO week starts on Monday and ends on Sunday
cal.set(Calendar.DAY_OF_WEEK, weekStartDay);// weekStartDay configurabale, as per
//user input Calendar.SUNDAY or Calendar.MONDAY or Calendar.TUEDAY; etc
String weekStartDate = sdf.format(cal.getTime());
cal.add(Calendar.DATE, 6);
String weekEndDate = sdf.format(cal.getTime());
LocalDate weekStart = LocalDate.of(Integer.valueOf(weekStartDate.substring(0, 4)),
Integer.valueOf(weekStartDate.substring(5, 7)), Integer.valueOf(weekStartDate.substring(8)));
if(weekStart.isBefore(startTime)) {
weekStart = startTime;
}
LocalDate weekEnd = LocalDate.of(Integer.valueOf(weekEndDate.substring(0, 4)),
Integer.valueOf(weekEndDate.substring(5, 7)), Integer.valueOf(weekEndDate.substring(8)));
if(weekEnd.isAfter(endTime)) {
weekEnd = endTime;
}
String weekStr = weekStart.toString()+"_"+weekEnd.toString();
return weekStr;
}
But when weekStartDay falls in lastweek of previous year then it gives the wrong vale of weekStartDate and weekStartEnd so please suggest me how to set yearnumber in java
Avinash, not the full answer but in-line with what Tom mentioned. A lot of convinient date time API's can be used since Java-8. Please feel free to customize this approach for the exact logic you may need
import java.time.DayOfWeek;
import java.time.temporal.ChronoField;
import java.time.temporal.IsoFields;
import static java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR;
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.temporal.TemporalAdjusters;
public class SO75013931 {
public static void main(String[] args) {
System.out.println(getWeekStart(LocalDate.parse("2021-12-28"),DayOfWeek.SUNDAY));
System.out.println(getWeekEnd(LocalDate.parse("2021-12-28"),DayOfWeek.SUNDAY));
}
//28-12-2021 TO 01-01-2022 && 02-01-2022 to 06-01-2022
private static String getWeekStart(LocalDate localDate, DayOfWeek weekStartDay) {
LocalDate weekStart = localDate.with(TemporalAdjusters.previous(weekStartDay));
return weekStart.isBefore(localDate) ? localDate.toString(): weekStart.toString();
}
private static String getWeekEnd(LocalDate localDate, DayOfWeek weekStartDay) {
LocalDate weekEnd = localDate.with(TemporalAdjusters.next(weekStartDay.minus(1)));
return weekEnd.isBefore(localDate) ? localDate.toString(): weekEnd.toString();
}
}
This would give
2021-12-28
2022-01-01
Again, the idea was to recommend usage of these API's as opposed to older util API's
input list
from date ex) 2020-10-01
to date ex) 2020-10-30
List [day of week] ex) [sun,mon....]
List [week] ex) [1,4,5]
I would like to know how to get a specific day of the week between the two dates.
Thank.
from date ex) 2020-10-01 to date ex) 2020-10-30
Your input string is already in the ISO8601 format for date and therefore it can be parsed without providing a DateTimeFormatter explicitly. In order to get the output string in a custom format (e.g. yyyy-MM-dd), you need to format the date object using DateTimeFormatter.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
String inputStrDate = "2020-10-01";
LocalDate date = LocalDate.parse(inputStrDate);
String outputStrDate = date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(outputStrDate);
}
}
Output:
2020-10-01
However, if your input is some other format, you will need to use DateTimeFormatter in order to parse it to a date object.
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class Main {
public static void main(String[] args) {
// Formatter for input string
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("dd-MM-yyyy");
String inputStrDate = "10-01-2020";
LocalDate date = LocalDate.parse(inputStrDate, inputFormat);
// Formatter for output string
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String outputStrDate = date.format(outputFormat);
System.out.println(outputStrDate);
}
}
Output:
2020-10-01
Learn more about date-time API from Trail: Date Time.
for(LocalDate d = fromDate; !d.isAfter(toDate); d = d.plusDays(1)) { // 일정 시작 ~ 끝 loop
for (Integer wf : weekOfMonth) {
for (Integer df : dayOfWeek) {
offDay = d.with(fieldWeek, wf)
.with(fieldDay, df);
if (d.getMonth() == offDay.getMonth() && !offDays.contains(offDay)) {
offDays.add(offDay);
}
}
}
}
Sorry for asking the wrong question.
And thank you very much.
I've already made it, but I've studied your code.
java.time
I too recommend that you use java.time, the modern Java date and time API, for your date work. My shot is:
LocalDate fromDate = LocalDate.of(2020, Month.OCTOBER, 1);
LocalDate toDate = LocalDate.of(2020, Month.OCTOBER, 30);
List<DayOfWeek> daysOfWeek = List.of(DayOfWeek.SUNDAY, DayOfWeek.MONDAY);
List<Integer> weeks = List.of(1, 4, 5);
if (! YearMonth.from(fromDate).equals(YearMonth.from(toDate))) {
throw new IllegalStateException("Covering more than one month is not yet supported");
}
WeekFields wf = WeekFields.SUNDAY_START;
for (int week : weeks) {
for (DayOfWeek dow : daysOfWeek) {
LocalDate date = fromDate.with(wf.weekOfMonth(), week)
.with(wf.dayOfWeek(), dow.get(wf.dayOfWeek()));
// Is date inside interval?
if (! (date.isBefore(fromDate) || date.isAfter(toDate))) {
System.out.println(date);
}
}
}
Output:
2020-10-18
2020-10-19
2020-10-25
2020-10-26
The dates printed are Sunday and Monday of weeks 4 and 5 of October defining weeks in the American way where the week begins on Sunday (since you mentioned Sunday first in your example list) and week 1 is the week of October 1. Sunday and Monday of week 1 are not printed because they fall before October 1, that is, in September.
Consider which week scheme you require. You may use for example WeekFields.ISO or WeekFields.of(Locale.getDefault()).
I am finding the week first, then the day of week, because to me this is the natural way. I need to use the WeekFields object for both adjustments to make sure that the chosen week scheme is respected.
If you need to cover more than one calendar month, iterate over the months and do the same for each. Also check that the result date falls within the month so duplicates near month borders are ignored.
I am making an Online Reservation System for a Restaurant in java. I want to know if a table is reserved. I have come up with this code.
I am not sure how to implement this logic.
public class Services {
public void reserveTable(String tableSize ,int time_limit){
String starting_time = "11:00 am";
String ending_time = "1:00 pm";
String current_time = "12:00 pm"; //time at which new order arrived
boolean reserved = false
for (String start = "11:00 am"; start <= ending_time; start ++){
if (current_time == start){
reserved = true;
}
}
}
}
You can use a DateTimeFormatter to parse your time strings into LocalTimes, and then check if the current is between the start and end:
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("h:mm a")
.toFormatter(Locale.ENGLISH);
LocalTime start = LocalTime.parse("11:00 am", formatter);
LocalTime end = LocalTime.parse("1:00 pm", formatter);
LocalTime current = LocalTime.parse("12:00 pm", formatter);
boolean reserved = false;
if (current.isAfter(start) && current.isBefore(end)) {
reserved = true;
}
Note that this won't work if the start and end span across midnight. e.g. start is 11pm and end is 2am. A current of 1am won't cause reserved to be set to true. For this case to work you need a date.
I have method that can take 2 different types of date formats:
MM/YY (credit card expiration date)
yyyyMMdd (funding expiration date)
Credit card expiration date is considered expired on the last day of that month. So, if cc date is May, 2017 (05/17), this cc is considered expired on 31th of May.
Funding expiration date will expire on the day it says it expires. So, if I am looking at it on the same day, it should return TRUE as funding has expired.
This is my code:
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public static boolean dateHasExpired(String dateInput)
{
LocalDate d = LocalDate.now();
LocalDate dateParsed = null;
if (dateInput.contains("/"))
{
int iYear = Integer.parseInt(dateInput.substring(dateInput.indexOf("/") + 1));
int iMonth = Integer.parseInt(dateInput.substring(0, dateInput.indexOf("/")));
int daysInMonth = LocalDate.of(iYear, iMonth, 1).getMonth().maxLength();
dateInput = iMonth+"/"+daysInMonth+"/"+iYear;
}
else
{
dateInput = ConvertDate(dateInput, "yyyyMMdd", "MM/dd/yyyy");
}
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
dateParsed = LocalDate.parse(dateInput, dateTimeFormatter);
return d.compareTo(dateParsed) <= 0;
}
public static String ConvertDate(String dateValue, String currentFormat, String requiredFormat)
{
SimpleDateFormat inFormatter = new SimpleDateFormat(currentFormat);
SimpleDateFormat outFormatter = new SimpleDateFormat(requiredFormat);
String outDate = "";
try
{
java.util.Date date = inFormatter.parse(dateValue);
outDate = outFormatter.format(date);
}
catch (ParseException e) {
ErrorLogger.logError ( e );
}
return outDate;
}
Does anyone know of better way of doing this?
I also noticed LocalDate doesn't account for Leap Year, so Feb 2015 has 29 days, just like Feb 2016, so my daysInMonth will not be a good number.
Looks like Date is more tollerant than LocalDate when it comes to year being yy and month 5 for month of May.
You can use java.time.YearMonth class, which contains a method that returns the last day of the respective month (and also takes care of leap years):
public static boolean dateHasExpired(String dateInput) {
LocalDate today = LocalDate.now();
LocalDate dateParsed = null;
if (dateInput.contains("/")) {
// parse credit card expiration date
YearMonth ym = YearMonth.parse(dateInput, DateTimeFormatter.ofPattern("MM/yy"));
// get last day of month (taking care of leap years)
dateParsed = ym.atEndOfMonth();
} else {
// parse funding expiration date
dateParsed = LocalDate.parse(dateInput, DateTimeFormatter.ofPattern("yyyyMMdd"));
}
// expired if today is equals or after dateParsed
return ! today.isBefore(dateParsed);
}
With this code (considering that today is May 02, 2017):
System.out.println(dateHasExpired("04/17")); // true
System.out.println(dateHasExpired("05/17")); // false
System.out.println(dateHasExpired("06/17")); // false
System.out.println(dateHasExpired("20170501")); //true
System.out.println(dateHasExpired("20170502")); // true
System.out.println(dateHasExpired("20170503")); // false
Note that atEndOfMonth() method takes care of leap years, so these will also work:
System.out.println(dateHasExpired("02/15"));
System.out.println(dateHasExpired("02/16"));
I've added a System.out.println(dateParsed); in dateHasExpired method, just to check if the date is being parsed correctly. And the output for the dates above are (respectively):
2015-02-28
2016-02-29
And dateHasExpired returns true for both, as expected.
I want to get the day on which the first Monday of a specific month/year will be.
What I have:
I basically have two int variables, one representing the year and one representing the month.
What I want to have:
I want to know the first Monday in this month, preferably as an int or Integer value.
For example:
I have 2014 and 1 (January), the first Monday in this month was the 6th, so I want to return 6.
Problems:
I thought I could do that with the Calendar but I am already having trouble setting up the calendar with only Year and Month available. Furthermore, I'm not sure how to actually return the first Monday of the month/year with Calendar.
I already tried this:
Calendar cal = Calendar.getInstance();
cal.set(this.getYear(),getMonth(), 1);
int montag = cal.getFirstDayOfWeek();
for( int j = 0; j < 7; j++ ) {
int calc = j - montag;
if( calc < 0 ) {
calc += 6;
}
weekDays[calc].setText(getDayString(calc));
}
Java.time
Use java.time library built into Java 8 and TemporalAdjuster. See Tutorial.
import java.time.DayOfWeek;
import java.time.LocalDate;
import static java.time.temporal.TemporalAdjusters.firstInMonth;
LocalDate now = LocalDate.now(); //2015-11-23
LocalDate firstMonday = now.with(firstInMonth(DayOfWeek.MONDAY)); //2015-11-02 (Monday)
If you need to add time information, you may use any available LocalDate to LocalDateTime conversion like
firstMonday.atStartOfDay() # 2015-11-02T00:00
getFirstDayOfWeek() returns which day is used as the start for the current locale. Some people consider the first day Monday, others Sunday, etc.
This looks like you'll have to just set it for DAY_OF_WEEK = MONDAY and DAY_OF_WEEK_IN_MONTH = 1 as that'll give you the first Monday of the month. To do the same for the year, first set the MONTH value to JANUARY then repeat the above.
Example:
private static Calendar cacheCalendar;
public static int getFirstMonday(int year, int month) {
cacheCalendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
cacheCalendar.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
cacheCalendar.set(Calendar.MONTH, month);
cacheCalendar.set(Calendar.YEAR, year);
return cacheCalendar.get(Calendar.DATE);
}
public static int getFirstMonday(int year) {
return getFirstMonday(year, Calendar.JANUARY);
}
Here's a simple JUnit that tests it: http://pastebin.com/YpFUkjQG
First of all you should know the latest version of java i.e. JAVA8
Get familiar with LocalDate in JAVA8
Then only go through below code
public class Test {
public static void main(String[] args) {
LocalDate date=LocalDate.of(2014,1, 1);
for(int i=0;i<date.lengthOfMonth();i++){
if("Monday".equalsIgnoreCase(date.getDayOfWeek().toString())){
break;
}else{
date=date.plusDays(1);
}
}
System.out.println(date.getDayOfMonth());
}
}
Joda-Time
The Joda-Time library offers a class, LocalDate, for when you need only a date without a time-of-day. The method getDayOfWeek returns a number you can compare to the constant MONDAY.
LocalDate localDate = new LocalDate( year, month, 1 );
while ( localDate.getDayOfWeek() != DateTimeConstants.MONDAY ) {
localDate = localDate.plusDays( 1 );
}
int firstMonday = localDate.getDayOfMonth();
Immutable Syntax
For thread-safety, Joda-Time uses immutable objects. So rather than modify field values in an existing object, we create a new instance based on the original.
java.time
As another answer by Abhishek Mishra says, the new java.time package bundled with Java 8 also offers a LocalDate class similar to Joda-Time.
The method getFirstDayOfWeek() is not helpful. Quoting its javadoc:
Gets what the first day of the week is; e.g., SUNDAY in the U.S., MONDAY in France
The following tested method uses modulus arithmetic to find the day of the month of the first Monday:
public static long getMondaysDay(int year, int month) {
try {
Date d = new SimpleDateFormat("d-M-yyyy").parse("1-" + month + "-" + year);
long epochMillis = d.getTime() + TimeZone.getDefault().getOffset(d.getTime());
return (12 - TimeUnit.MILLISECONDS.toDays(epochMillis) % 7) % 7;
} catch (ParseException ignore) { return 0; } // Never going to happen
}
Knowing that the first day of the epoch was Thursday, this works by using modulus arithmetic to calculate the day of the epoch week, then how many days until the next Monday, then modulus again in case the first falls before Thursday. The magic number 12 is 4 (the number of days from Thursday to Monday) plus 1 because days of the month start from 1 plus 7 to ensure positive results after subtraction.
The simplest way is:
LocalDate firstSundayOfNextMonth = LocalDate
.now()
.with(firstDayOfNextMonth())
.with(nextOrSame(DayOfWeek.MONDAY));
Here is a general function to get the nth DAY_OF_WEEK of a given month. You can use it to get the first Monday of any given month.
import java.util.Calendar;
public class NthDayOfWeekOfMonth {
public static void main(String[] args) {
// get first Monday of July 2019
Calendar cal = getNthDayOfWeekOfMonth(2019,Calendar.JULY,1,Calendar.MONDAY);
System.out.println(cal.getTime());
// get first Monday of August 2019
cal = getNthDayOfWeekOfMonth(2019,Calendar.AUGUST,1,Calendar.MONDAY);
System.out.println(cal.getTime());
// get third Friday of September 2019
cal = getNthDayOfWeekOfMonth(2019,Calendar.SEPTEMBER,3,Calendar.FRIDAY);
System.out.println(cal.getTime());
}
public static Calendar getNthDayOfWeekOfMonth(int year, int month, int n, int dayOfWeek) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.YEAR,year);
cal.set(Calendar.MONTH,month);
cal.set(Calendar.DAY_OF_MONTH,1);
int dayDiff = dayOfWeek-cal.get(Calendar.DAY_OF_WEEK);
if (dayDiff<0) {
dayDiff+=7;
}
dayDiff+=7*(n-1);
cal.add(Calendar.DATE, dayDiff);
return cal;
}
}
Output:
Mon Jul 01 00:00:00 EDT 2019
Mon Aug 05 00:00:00 EDT 2019
Fri Sep 20 00:00:00 EDT 2019
Lamma Date library is very good for this use case.
#Test
public void test() {
assertEquals(new Date(2014, 1, 6), firstMonday(2014, 1));
assertEquals(new Date(2014, 2, 3), firstMonday(2014, 2));
assertEquals(new Date(2014, 3, 3), firstMonday(2014, 3));
assertEquals(new Date(2014, 4, 7), firstMonday(2014, 4));
assertEquals(new Date(2014, 5, 5), firstMonday(2014, 5));
assertEquals(new Date(2014, 6, 2), firstMonday(2014, 6));
}
public Date firstMonday(int year, int month) {
Date firstDayOfMonth = new Date(year, month, 1);
return firstDayOfMonth.nextOrSame(DayOfWeek.MONDAY);
}
Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("MMM/dd/YYYY");
calendar.set(Calendar.MONTH,Calendar.JUNE);
calendar.set(Calendar.DAY_OF_MONTH,1);
int day = (Calendar.TUESDAY-calendar.get(Calendar.DAY_OF_WEEK));
if(day<0){
calendar.add(Calendar.DATE,7+(day));
}else{
calendar.add(Calendar.DATE,day);
}
System.out.println("First date is "+sdf.format(calendar.getTime()));
Get the All Monday of a month
public class AllMonday {
public static void main(String[] args){
System.out.println(weeksInCalendar(YearMonth.now()));
}
public static List<LocalDate> weeksInCalendar(YearMonth month) {
List<LocalDate> firstDaysOfWeeks = new ArrayList<>();
for (LocalDate day = firstDayOfCalendar(month);
stillInCalendar(month, day); day = day.plusWeeks(1)) {
firstDaysOfWeeks.add(day);
}
return firstDaysOfWeeks;
}
private static LocalDate firstDayOfCalendar(YearMonth month) {
DayOfWeek FIRST_DAY_OF_WEEK = DayOfWeek.of(1);
System.out.println( month.atDay(1).with(FIRST_DAY_OF_WEEK));
return month.atDay(1).with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
}
private static boolean stillInCalendar(YearMonth yearMonth, LocalDate day) {
System.out.println(!day.isAfter(yearMonth.atEndOfMonth()));
return !day.isAfter(yearMonth.atEndOfMonth());
}
}