Breakdown year in weeks - Java 8 - java-8

I want to create a "select", that when selecting a year in another "select", I load all the weeks of that year, from Monday to Friday:
Example, if I select 2018 my "select" would be something like this.
1 - 01/01/18 - 07/01/18
2 - 01/08/18 - 01/14/18
3 - 15/01/18 - 01/21/10
......
52 - 12/24/18 - 12/30/18
The data was prepared in the back-end with java. To then send it as an array of string to the front-end

Avoid legacy date-time classes
The modern solution uses java.time classes. These supplanted the terribly flawed legacy classes such as Date & Calendar.
Looping
Determine the first day of year. And the first day of the following year, as our limit.
Year year = Year.of( 2018 );
LocalDate firstOfYear = year.atDay( 1 );
LocalDate firstOfFollowingYear = year.plusYears( 1 ).atDay( 1 );
Use a TemporalAdjuster to move through time. The TemporalAdjusters class (note the plural) happens to offer an adjuster implementation for our needs, previousOrSame. Use that to move back in time to get a Monday, if the 1st of year is not already Monday.
TemporalAdjuster adjuster = TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY );
LocalDate firstMondayOfYear = firstOfYear.with( adjuster );
Define a list to hold our weekly report.
List < String > weeks = new ArrayList <>( 53 );
Define a formatter to generate the text for our weekly report. The DateTimeFormatter class can automatically localize, so we need not hard-code a specific format.
Locale locale = Locale.forLanguageTag( "es-ES" ); // Spain locale.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( locale );
Loop through the weeks of the year. We increment one week at a time, until hitting the following year.
int nthWeekOfYear = 0;
LocalDate localDate = firstMondayOfYear;
while ( localDate.isBefore( firstOfFollowingYear ) ) {
nthWeekOfYear++;
String output = nthWeekOfYear + " - " + localDate.format( formatter ) + " - " + localDate.plusDays( 6 ); // Using Fully-Closed weeks, where both beginning and end are inclusive. In contrast to Half-Open.
weeks.add( output );
// Set up next loop.
localDate = localDate.plusWeeks( 1 );
}
Convert from a List to an array, per your directions in the Question.
String[] results = weeks.toArray( new String[ weeks.size() ] );
Dump to console.
System.out.println( "results = " + Arrays.toString( results ) );
Streams
We could rewrite this code by using streams and lambdas. This requires Java 9+.
The LocalDate#datesUntil method produces a Stream of LocalDate objects.
While I do not necessarily recommend this code, I found it interesting that we can write the entire routine as a one-liner.
int inputYear = 2018;
List < String > weeks =
Year
.of( inputYear )
.atDay( 1 )
.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) )
.datesUntil( Year.of( inputYear ).plusYears( 1 ).atDay( 1 ) , Period.ofWeeks( 1 ) )
.map( localDate -> localDate.format( DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.forLanguageTag( "es-ES" ) ) ) + " - " + localDate.plusDays( 6 ).format( DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( Locale.forLanguageTag( "es-ES" ) ) ) )
.toList(); // Before Java 16, change to .collect( Collectors.toList()); or .collect( Collectors.toUnmodifiableList());
When run.
weeks = [1/1/18 - 7/1/18, 8/1/18 - 14/1/18, 15/1/18 - 21/1/18, 22/1/18 - 28/1/18, 29/1/18 - 4/2/18, 5/2/18 - 11/2/18, 12/2/18 - 18/2/18, 19/2/18 - 25/2/18, 26/2/18 - 4/3/18, 5/3/18 - 11/3/18, 12/3/18 - 18/3/18, 19/3/18 - 25/3/18, 26/3/18 - 1/4/18, 2/4/18 - 8/4/18, 9/4/18 - 15/4/18, 16/4/18 - 22/4/18, 23/4/18 - 29/4/18, 30/4/18 - 6/5/18, 7/5/18 - 13/5/18, 14/5/18 - 20/5/18, 21/5/18 - 27/5/18, 28/5/18 - 3/6/18, 4/6/18 - 10/6/18, 11/6/18 - 17/6/18, 18/6/18 - 24/6/18, 25/6/18 - 1/7/18, 2/7/18 - 8/7/18, 9/7/18 - 15/7/18, 16/7/18 - 22/7/18, 23/7/18 - 29/7/18, 30/7/18 - 5/8/18, 6/8/18 - 12/8/18, 13/8/18 - 19/8/18, 20/8/18 - 26/8/18, 27/8/18 - 2/9/18, 3/9/18 - 9/9/18, 10/9/18 - 16/9/18, 17/9/18 - 23/9/18, 24/9/18 - 30/9/18, 1/10/18 - 7/10/18, 8/10/18 - 14/10/18, 15/10/18 - 21/10/18, 22/10/18 - 28/10/18, 29/10/18 - 4/11/18, 5/11/18 - 11/11/18, 12/11/18 - 18/11/18, 19/11/18 - 25/11/18, 26/11/18 - 2/12/18, 3/12/18 - 9/12/18, 10/12/18 - 16/12/18, 17/12/18 - 23/12/18, 24/12/18 - 30/12/18, 31/12/18 - 6/1/19]
A little more reasonable would be extracting the formatter and the Year.
Locale locale = Locale.forLanguageTag( "es-ES" ); // Spain locale.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.SHORT ).withLocale( locale );
Year year = Year.of( 2018 );
List < String > weeks =
year
.atDay( 1 )
.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) )
.datesUntil( year.plusYears( 1 ).atDay( 1 ) , Period.ofWeeks( 1 ) )
.map( localDate -> localDate.format( formatter ) + " - " + localDate.plusDays( 6 ).format( formatter ) )
.toList(); // Before Java 16, change to .collect( Collectors.toList()); or .collect( Collectors.toUnmodifiableList());
ISO 8601
If your definition of week complies with the ISO 8601 definition of week:
First day of week is Monday
Week # 1 of year contains the first Thursday of the calendar year
… then I suggest adding the ThreeTen-Extra library to your project to utilize the YearWeek class.

public class Weeks {
public static void main(String[] args) {
int year = 2018;
int weeks = getNumWeeksForYear(year);
for (int i = 1; i < weeks; i++) {
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.WEEK_OF_YEAR, i);
calendar.set(Calendar.YEAR, year);
Date monday = calendar.getTime();
calendar.add(Calendar.DATE, 6);
Date sunday = calendar.getTime();
System.out.println("week" + i);
System.out.println(monday);
System.out.println(sunday);
}
}
public static int getNumWeeksForYear(int year) {
Calendar c = Calendar.getInstance();
c.set(year, 0, 1);
return c.getMaximum(Calendar.WEEK_OF_YEAR);
}
}

Related

Java 8 - SQL Timestamp to Instant with properly formatted time

I've read through the available q and a on SO, but nothing I have found answers my question of how to format my time in 12hour format.
Following is my code that runs a query on a MySQL database and returns results, checking to see if an appointment is within 15 minutes of login so an alert can pop.
public void apptCheck(int userId) throws SQLException {
// this method checks for an appointment occurring within 15 minutes of login
Statement apptStatement = DBQuery.getStatement();
String apptQuery = "Select apt.start, cs.customerName from DBName.appointment apt "
+ "JOIN DBName.customer cs ON cs.customerId = apt.customerId WHERE "
+ "userId = " + userId + " AND start >= NOW() AND start < NOW() + interval 16 minute";
apptStatement.execute(apptQuery);
ResultSet apptRs = apptStatement.getResultSet();
while(apptRs.next()) {
Timestamp apptTime = apptRs.getTimestamp("start");
ResourceBundle languageRB = ResourceBundle.getBundle("wgucms/RB", Locale.getDefault());
Alert apptCheck = new Alert(AlertType.INFORMATION);
apptCheck.setHeaderText(null);
apptCheck.setContentText(languageRB.getString("apptSoon") + " " + apptTime.toInstant().atZone(ZoneId.systemDefault()));
apptCheck.showAndWait();
}
My result is:
I want the time to display 3:00, not the 19:00 - 06:00. How can I make that happen?
ZonedDateTime zonedDateTime=ZonedDateTime.of(apptTime.toLocalDateTime(),ZoneId.systemDefault());
You can use ZonedDateTime and format the time as you want.
docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html ZonedDateTime has a lot of features you can see all here and you can get the hour, minute, day etc.
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm:ss");
String formattedString = zonedDateTime.format(formatter);
if you only want time in 12hour format you can use this
I found the solution which will perform the UTC to local time conversion and then format the time so that the resulting alert is in 12 hour time format without the date or time zone info. Here is the full code:
while(apptRs.next()) {
Timestamp apptTime = apptRs.getTimestamp("start");
// perform time conversion from UTC to User Local Time
ZoneId zidApptTime = ZoneId.systemDefault();
ZonedDateTime newZDTApptTime = apptTime.toLocalDateTime().atZone(ZoneId.of("UTC"));
ZonedDateTime convertedApptTime = newZDTApptTime.withZoneSameInstant(zidApptTime);
ResourceBundle languageRB = ResourceBundle.getBundle("wgucms/RB", Locale.getDefault());
Alert apptCheck = new Alert(AlertType.INFORMATION);
apptCheck.setHeaderText(null);
// set the Alert text and format in 12 hour format
apptCheck.setContentText(languageRB.getString("apptSoon") +
convertedApptTime.toInstant().atZone(ZoneId.systemDefault())
.format(DateTimeFormatter.ofPattern("h:mm a")) + ".");
apptCheck.showAndWait();
}

Writing a condition logics in kotlin in a better way in kotlin

I have a following condition logic and want to make it simple, is there a way to make it better without too much || && ? Some sample or example will be lovely! I would love to hear from you!
Logic that I want to achieve
From 0:00 on and 3 days before the birth month,
condition is the birth month is once or January 31st and
the present is run every December 29-31
val birthYear = child.birthYear!!.toInt()
val birthMonth = child.birthMonth!!.toInt()
val date = DateTime()
val year = date.year
val month = date.month
val day = date.day
val maxDayOfMonth = date.maxDayOfMonth
class DateTime {
private var mCalendar: Calendar = Calendar.getInstance().also { it.clear() }
val year: Int
get() = mCalendar.get(Calendar.YEAR)。。。。。
The following is the logic that I want to make it simpler
return date.year > child.birthYear!!.toInt() &&
((birthMonth == 1 && month == 12 || birthMonth - 1 == month)
&& day >= maxDayOfMonth - 2 || birthMonth == month)

How to obtain first date of each month based on given year range in Nifi flow

I would like to know what could be the best way to obtain the starting date values for each month based on the date range.
For example: If I am given a year range of 2015-11-10 and 2018-01-15(format YYYY-mm-dd). Then I would like to extract following dates:
2015-12-01
2016-01-01
.
.
2018-01-01
You can try to use this flow for generating the first day of each month in the provided date range.
Overall flow
Step 1 Configuration: Start
Step 2 Configuration: Configure Date Range
Provide the start and end dates as configuration parameters via this step.
Step 3 Configuration: Generate First Dates For Months
This uses a Groovy script, which is provided below
Groovy script
flowFile = session.get();
if(!flowFile)
return;
DATE_FORMAT = 'yyyy-MM-dd';
startDate = Date.parse(DATE_FORMAT, flowFile.getAttribute("start_date"));
endDate = Date.parse(DATE_FORMAT, flowFile.getAttribute("end_date"));
allFirstDates = "";
Calendar calendar = Calendar.getInstance();
Set firstDaysOfMonths = new LinkedHashSet();
for (int i = 0; i <= endDate-startDate; i++) {
calendar.setTime(startDate.plus(i));
calendar.set(Calendar.DAY_OF_MONTH, 1);
firstDayOfMonth = calendar.getTime();
if (firstDayOfMonth.compareTo(startDate) >= 0) {
firstDaysOfMonths.add(calendar.getTime().format(DATE_FORMAT));
}
}
firstDaysOfMonths.each {
firstDayOfMonth -> allFirstDates = allFirstDates + firstDayOfMonth + "\n";
}
flowFile = session.putAttribute(flowFile,"all_first_dates", allFirstDates );
session.transfer(flowFile,REL_SUCCESS)
Step 4 Configuration: View Result
Output of run:
When the flow is run, the attribute all_first_dates will be populated with the first dates of each month in the date range.

How to use date helper in CodeIgniter to find time conflict?

I have a database table
TABLE subject_loads
id (int)
subject_name (varchar)
time_start (time)
time_end (time)
time_diff (decimal)
When I save it on database, it will first check whether the time is not conflicting from the other time already inputed. If it's okay, then compute the time_start and time_end to give me a difference between the two.
Example, 7:30 AM - 8:30 AM is already in database, when i input 8:00 AM - 9:00 AM it will say "conflicting with the other time". Only I can input before 7:30 AM or after 8:30 AM that doesn't overlap from 7:30 AM - 8:30 AM.
Can someone help on how to do this?
First you need to check if overlapping values (compared to new value) already exist. You will do that with:
$query = $this->db->get_where('subject_loads', array('time_start >= ' => $time_start, 'time_end <= ' => $time_end));
if((int)$query->num_rows() > 0)
{
//similar values exist
}
else
{
//you are free to insert values
}
Second part of issue:
$hm1 = "2:12 AM";
$hm2 = "4:41 PM";
$e = conv($hm2) - conv($hm1);
echo $e;
function conv($time)
{
$expl_time = explode(' ', $time);
$t = explode(":", $expl_time[0]);
if ($expl_time[1] == 'PM' || $expl_time[1] == 'pm')
{
$t[0] += 12;
}
return ($t[0] + round($t[1]/60, 1, PHP_ROUND_HALF_UP));
}

failed to manipulate my Arraylist

I need help , I have an arrayList of objects . This object contains multiple fields I'm interested in this question by two date fields (date_panne date_mise and running) and two other time fields (heure_panne and time start),
And I would like to obtain the sum of the difference between (date_panne, heure_panne) and (date_mise_en_marche; heure_mise_en_marche) to give the total time of failure.
if someone can help me please I will be gratful this is my function :
public String disponibile() throws Exception {
int nbreArrets = 0;
List<Intervention> allInterventions = interventionDAO.fetchAllIntervention();
List<Intervention> listInterventions = new ArrayList<Intervention>();
for (Intervention currentIntervention : allInterventions) {
if (currentIntervention.getId_machine() == this.intervention.getId_machine()
&& currentIntervention.getDate_panne().compareTo(getProductionStartDate()) >= 0
&& currentIntervention.getDate_panne().compareTo(getProductionEndDate()) <= 0) {
listInterventions.add(currentIntervention);
}
}
savedInterventionList = listInterventions;
return "successView" ;
}
Assuming the the dates are truncated to the day and are of type java.util.Date, and that the times only contain hours, minutes, seconds and milliseconds and are also of type Date, start by creating a method like
private Date combine(Date dateOnly, Date timeOnly) {
Calendar dateCalendar = Calendar.getInstance();
dateCalendar.setTime(dateOnly);
Calendar timeCalendar = Calendar.getInstance();
timeCalendar.setTime(timeOnly);
dateCalendar.add(Calendar.HOUR_OF_DAY, timeCalendar.get(Calendar.HOUR_OF_DAY));
dateCalendar.add(Calendar.MINUTE, timeCalendar.get(Calendar.MINUTE));
dateCalendar.add(Calendar.SECOND, timeCalendar.get(Calendar.SECOND));
dateCalendar.add(Calendar.MILLISECOND, timeCalendar.get(Calendar.MILLISECOND));
return dateCalendar.getTime();
}
Now, it's simply a matter of looping through the interventions you want to sum, computing the difference between the dates as milliseconds, and add them:
long totalMillis = 0L;
for (Intervention intervention : interventions) {
Date marche = combine(intervention.getDateMiseEnMarche(), intervention.getTimeMiseEnMarche());
Date panne = combine(intervention.getDatePanne(), intervention.getTimePanne());
long differenceInMillis = marche.getTime() - panne.getTime();
totalMillis += differenceInMillis;
}

Resources