Get the most recent "Monday 05:30" Unix time in Go? - go

Is there a Time library function or another good way to get the most recent weekday, hour, minute combination in Unix time? For example, given:
day: Monday
hour: 11
minute: 30
And it's currently Tuesday, I want the Unix time for yesterday at 11:30am. Some languages / libraries have support for thing but I cannot find something in Go that would make this easy. Any advice?

If you look at the definition of Weekday, you'll see that Sunday is 0, Monday is 1, etc. So to get to the last Monday, you have to do go back today-Monday, and move back to 11:30 that day. However, this doesn't work if it is already Monday and before 11:30, so you need to check for that:
now:=time.Now()
dayOffset:=now.Weekday()-time.Monday
targetDate:=now.AddDate(0,0,-int(dayOffset))
targetDate=time.Date(targetDate.Year(),targetDate.Month(),targetDate.Day(),11,30,0,0,targetDate.Location())
if targetDate.After(now) {
targetDate=targetDate.AddDate(0,0,-7)
}

My attempt at a simple and intuitive solution. See code comments for explanation
package main
import (
"fmt"
"time"
)
func main() {
// The target day / hour / minute
const (
day = time.Monday
hour = 21
minute = 0
)
// The starting time to work from
startTime := time.Now()
// Create the time on that day with the desired hour and minute
t := time.Date(startTime.Year(), startTime.Month(), startTime.Day(), hour, minute, 0, 0, startTime.Location())
// As long as we're on the wrong weekday, or not before the start time, back up one day
for t.Weekday() != day || !t.Before(startTime){
t = t.AddDate(0, 0, -1)
}
// Print the time, and it's Unix timestamp.
fmt.Println(t, t.Unix())
}

Related

How reduce one day from current in Pipeline Jenkins?

I can't reduce one day from current
def now = new Date();
print(now); // print Fri Sep 06 13:10:03 EEST 2019
print(now - 1.days); // not working
print(now - 1); // not working
Please help me. Thanks in advance
the solution works. There might be 2 problems though:
- the snippet you wrote has to be included in a script if you plan to execute it in a stage
- the DateGroovyMethods is not allowed to be used by default. You need administrator rights and to check the build log to allow the execution of that stuff.
The error will look like this:
Scripts not permitted to use staticMethod org.codehaus.groovy.runtime.DateGroovyMethods minus java.util.Date int. Administrators can decide whether to approve or reject this signature.
This is my test example:
pipeline {
agent any
stages {
stage('MyDate test') {
steps {
script {
def date = new Date()
print date
print date - 1
}
}
}
}
}
EDIT:
If you are not an administrator, you can replace the script block with sh 'date -d "-1 days"'
You can also use minus(1) instead of - 1:
def now = new Date();
print(now);
print(now.minus(1))
The best thing to do is to skip the use of Date entirely. java.util.Date is literally the oldest java implementation of date and time. The newest comes with Java 8. You can do it like this:
groovy:000> java.time.LocalDateTime.now().minusDays(1)
===> 2019-09-08T12:07:30.835557
groovy:000>
You can convert from Date to LocalDateTime as well if needed.
(Java syntax used here, as I do not know Groovy.)
tl;dr
Subtract 24-hours.
Instant.now().minus( Duration.ofHours( 24 ) ) // UTC.
…or…
Subtract one calendar day.
ZonedDateTime.now( ZoneId.of( "America/New_York" ) ).minusDays( 1 ) ) // Time zone for Toledo, Ohio, US.
java.time
Never use java.util.Date. That terrible class was supplanted years ago by the modern java.time classes with the adoption of JSR 310. Specifically replaced by Instant.
I can't reduce one day from current
What do you mean by “one day”?
Generic 24-hour days
Do you mean to subtract 24-hours?
Duration d = Duration.ofHours( 24 ) ;
Instant instant = Instant.now() ;
Instant twentyFourHoursAgo = instant.minus( d ) ;
The Instant class represents a moment in UTC with a resolution of nanoseconds.
Run this code live at IdeOne.com.
instant.now().toString(): 2019-09-09T18:48:17.106438Z
twentyFourHoursAgo.toString(): 2019-09-08T18:48:17.106438Z
Calendar days
Do you mean to subtract one calendar day?
This requires a time zone. For any given moment, the date varies around the globe by time zone. It may be “tomorrow” in Tokyo Japan while still “yesterday” in Toledo Ohio US.
Specify a time zone with ZoneId to capture the current moment as seen through the wall-clock time used by the people of a particular region in a ZonedDateTime object.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
ZonedDateTime oneDayAgo = zdt.minusDays( 1 ) ;
Run this code live at IdeOne.com.
zdt.toString(): 2019-09-10T03:48:17.147539+09:00[Asia/Tokyo]
oneDayAgo.toString(): 2019-09-09T03:48:17.147539+09:00[Asia/Tokyo]
Convert
If you must have a java.util.Date object to interoperate with old code not yet updated to java.time, you can convert. See the new to…/from… conversion methods added to the old classes.
java.util.Date javaUtilDate =
Date.from( Instant.now().minus( Duration.ofHours( 24 ) ) ) ;
…or…
java.util.Date javaUtilDate =
Date.from( ZonedDateTime.now( ZoneId.of( "Asia/Tokyo" ) ).minusDays( 1 ) ) ) ;
Keep in mind that java.util.Date.toString method tells a lie, dynamically applying the JVM’s current default time zone while generating the text. One of many reasons to avoid this badly-designed class.

what is correct way to use golang AddDate to calculate date

Today is 2018-11-1, I use AddDate to calculate 7 days:
startTime := time.Now().AddDate(0, 0, -7).Unix(), but 2018-10-25 still exist. What is the correct way to calculate date use AddDate method?
Package time
import "time"
func (Time) AddDate
func (t Time) AddDate(years int, months int, days int) Time
AddDate returns the time corresponding to adding the given number of
years, months, and days to t. For example, AddDate(-1, 2, 3) applied
to January 1, 2011 returns March 4, 2010.
AddDate normalizes its result in the same way that Date does, so, for
example, adding one month to October 31 yields December 1, the
normalized form for November 31.
startTime := time.Now().AddDate(0, 0, -7) calculates the time minus 7 (-7) days or 7 days ago.
For example,
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now().Round(0))
startTime := time.Now().AddDate(0, 0, -7)
fmt.Println(startTime)
}
Output (right now in the US it is 2018-10-31 21:30:40 EDT):
2018-10-31 21:30:40.977401051 -0400 EDT
2018-10-24 21:30:40.977510166 -0400 EDT
In your time zone, it is currently 2018-11-01, so minus 7 (-7) days or 7 days ago is 2018-10-25.
Note: There are two ways to count days. For age, today you are one day older than yesterday. For pay, working yesterday and today is two days pay.

Algorithm to calculate a date for complex occupation management

Hello fellow Stack Overflowers,
I have a situation, where I need some help choosing the best way to make an algorithm work, the objective is to manage the occupation of a resource (Lets consider the resource A) to have multiple tasks, and where each task takes a specified amount of time to complete. At this first stage I don't want to involve multiple variables, so lets keep it the simple way, lets consider he only has a schedule of the working days.
For example:
1 - We have 1 resource, resource A
2 - Resource A works from 8 am to 4 pm, monday to friday, to keep it simple by now, he doesn't have lunch for now, so, 8 hours of work a day.
3 - Resource A has 5 tasks to complete, to avoid complexity at this level, lets supose each one will take exactly 10 hours to complete.
4 - Resource A will start working on this tasks at 2018-05-16 exactly at 2 pm.
Problem:
Now, all I need to know is the correct finish date for all the 5 tasks, but considering all the previous limitations.
In this case, he has 6 working days and additionaly 2 hours of the 7th day.
The expected result that I want would be: 2018-05-24 (at 4 pm).
Implementation:
I thought about 2 options, and would like to have feedback on this options, or other options that I might not be considering.
Algorithm 1
1 - Create a list of "slots", where each "slot" would represent 1 hour, for x days.
2 - Cross this list of slots with the hour schedule of the resource, to remove all the slots where the resource isn't here. This would return a list with the slots that he can actually work.
3 - Occupy the remaining slots with the tasks that I have for him.
4 - Finnaly, check the date/hour of the last occupied slot.
Disadvantage: I think this might be an overkill solution, considering that I don't want to consider his occupation for the future, all I want is to know when will the tasks be completed.
Algorithm 2
1 - Add the task hours (50 hours) to the starting date, getting the expectedFinishDate. (Would get expectedFinishDate = 2018-05-18 (at 4 pm))
2 - Cross the hours, between starting date and expectedFinishDate with the schedule, to get the quantity of hours that he won't work. (would basically get the unavailable hours, 16 hours a day, would result in remainingHoursForCalc = 32 hours).
3 - calculate new expectedFinishDate with the unavailable hours, would add this 32 hours to the previous 2018-05-18 (at 4 pm).
4 - Repeat point 2 and 3 with new expectedFinishDate untill remainingHoursForCalc = 0.
Disadvantage: This would result in a recursive method or in a very weird while loop, again, I think this might be overkill for calculation of a simple date.
What would you suggest? Is there any other option that I might not be considering that would make this simpler? Or you think there is a way to improve any of this 2 algorithms to make it work?
Improved version:
import java.util.Calendar;
import java.util.Date;
public class Main {
public static void main(String args[]) throws Exception
{
Date d=new Date();
System.out.println(d);
d.setMinutes(0);
d.setSeconds(0);
d.setHours(13);
Calendar c=Calendar.getInstance();
c.setTime(d);
c.set(Calendar.YEAR, 2018);
c.set(Calendar.MONTH, Calendar.MAY);
c.set(Calendar.DAY_OF_MONTH, 17);
//c.add(Calendar.HOUR, -24-5);
d=c.getTime();
//int workHours=11;
int hoursArray[] = {1,2,3,4,5, 10,11,12, 19,20, 40};
for(int workHours : hoursArray)
{
try
{
Date end=getEndOfTask(d, workHours);
System.out.println("a task starting at "+d+" and lasting "+workHours
+ " hours will end at " +end);
}
catch(Exception e)
{
System.out.println(e.getMessage());
}
}
}
public static Date getEndOfTask(Date startOfTask, int workingHours) throws Exception
{
int totalHours=0;//including non-working hours
//startOfTask +totalHours =endOfTask
int startHour=startOfTask.getHours();
if(startHour<8 || startHour>16)
throw new Exception("a task cannot start outside the working hours interval");
System.out.println("startHour="+startHour);
int startDayOfWeek=startOfTask.getDay();//start date's day of week; Wednesday=3
System.out.println("startDayOfWeek="+startDayOfWeek);
if(startDayOfWeek==6 || startDayOfWeek==0)
throw new Exception("a task cannot start on Saturdays on Sundays");
int remainingHoursUntilDayEnd=16-startHour;
System.out.println("remainingHoursUntilDayEnd="+remainingHoursUntilDayEnd);
/*some discussion here: if task starts at 12:30, we have 3h30min
* until the end of the program; however, getHours() will return 12, which
* substracted from 16 will give 4h. It will work fine if task starts at 12:00,
* or, generally, at the begining of the hour; let's assume a task will start at HH:00*/
int remainingDaysUntilWeekEnd=5-startDayOfWeek;
System.out.println("remainingDaysUntilWeekEnd="+remainingDaysUntilWeekEnd);
int completeWorkDays = (workingHours-remainingHoursUntilDayEnd)/8;
System.out.println("completeWorkDays="+completeWorkDays);
//excluding both the start day, and the end day, if they are not fully occupied by the task
int workingHoursLastDay=(workingHours-remainingHoursUntilDayEnd)%8;
System.out.println("workingHoursLastDay="+workingHoursLastDay);
/* workingHours=remainingHoursUntilDayEnd+(8*completeWorkDays)+workingHoursLastDay */
int numberOfWeekends=(int)Math.ceil( (completeWorkDays-remainingDaysUntilWeekEnd)/5.0 );
if((completeWorkDays-remainingDaysUntilWeekEnd)%5==0)
{
if(workingHoursLastDay>0)
{
numberOfWeekends++;
}
}
System.out.println("numberOfWeekends="+numberOfWeekends);
totalHours+=(int)Math.min(remainingHoursUntilDayEnd, workingHours);//covers the case
//when task lasts 1 or 2 hours, and we have maybe 4h until end of day; that's why i use Math.min
if(completeWorkDays>0 || workingHoursLastDay>0)
{
totalHours+=8;//the hours of the current day between 16:00 and 24:00
//it might be the case that completeWorkDays is 0, yet the task spans up to tommorrow
//so we still have to add these 8h
}
if(completeWorkDays>0)//redundant if, because 24*0=0
{
totalHours+=24*completeWorkDays;//for every 8 working h, we have a total of 24 h that have
//to be added to the date
}
if(workingHoursLastDay>0)
{
totalHours+=8;//the hours between 00.00 AM and 8 AM
totalHours+=workingHoursLastDay;
}
if(numberOfWeekends>0)
{
totalHours+=48*numberOfWeekends;//every weekend between start and end dates means two days
}
System.out.println("totalHours="+totalHours);
Calendar calendar=Calendar.getInstance();
calendar.setTime(startOfTask);
calendar.add(Calendar.HOUR, totalHours);
return calendar.getTime();
}
}
You may adjust the hoursArray[], or d.setHours along with c.set(Calendar.DAY_OF_MONTH, to test various start dates along with various task lengths.
There is still a bug , due to the addition of the 8 hours between 16:00 and 24:00:
a task starting at Thu May 17 13:00:00 EEST 2018 and lasting 11 hours will end at Sat May 19 00:00:00 EEST 2018.
I've kept a lot of print statements, they are useful for debugging purposes.
Here is the terminology explained:
I agree that algorithm 1 is overkill.
I think I would make sure I had the conditions right: hours per day (8), working days (Mon, Tue, Wed, Thu, Fri). Would then divide the hours required (5 * 10 = 50) by the hours per day so I know a minimum of how many working days are needed (50 / 8 = 6). Slightly more advanced, divide by hours per week first (50 / 40 = 1 week). Count working days from the start date to get a first shot at the end date. There was probably a remainder from the division, so use this to determine whether the tasks can end on this day or run into the next working day.

Swift 2.0+ finding the day of the week a month starts

I am using Swift 2.0+ and need it to be compatible with iOS 8.0+. I want to find out what day of the week a month starts. For example, November 15 would return Sunday, December 15 would return Tuesday, and January 16 would return Friday. I think the best approach would be to get the current day of the week and day of the month then count backwards until you reach 1 and get that day. Currently I have
// Returns the day of the week as an integer 1 being Sunday and 7 being Saturday
func dayOfWeek() -> Int {
let components = calender.component(NSCalendarUnit.Weekday, fromDate: t)
return components
}
Which calculates the current day of the week, after that I hit a roadblock.
I found the answer to be
// This function should return the value I need 0 being Sunday and 6 being Saturday
func dayMonthStarted() -> Int {
// 0 -> Sunday 6 -> Saturday
var component = calender.component(NSCalendarUnit.Day, fromDate: date)
var day = dayOfWeek()
while component > 1 {
component--
if day == 0 {
day = 6
} else {
day--
}
}
return day - 1
}

Set time part of DateTime in ruby

Say I have a datetime object eg DateTime.now. I want to set hours and minutes to 0 (midnight). How can I do that?
Within a Rails environment:
Thanks to ActiveSupport you can use:
DateTime.now.midnight
DateTime.now.beginning_of_day
OR
DateTime.now.change({ hour: 0, min: 0, sec: 0 })
# More concisely
DateTime.now.change({ hour: 0 })
Within a purely Ruby environment:
now = DateTime.now
DateTime.new(now.year, now.month, now.day, 0, 0, 0, now.zone)
OR
now = DateTime.now
DateTime.parse(now.strftime("%Y-%m-%dT00:00:00%z"))
Nevermind, got it. Need to create a new DateTime:
DateTime.new(now.year, now.month, now.day, 0, 0, 0, 0)
Warning: DateTime.now.midnight and DateTime.now.beginning_of_day return the same value (which is the zero hour of the current day - midnight does not return 24:00:00 as you would expect from its name).
So I am adding this as further info for anyone who might use the accepted answer to calculate midnight x days in the future.
For example, a 14 day free trial that should expire at midnight on the 14th day:
DateTime.now.midnight + 14.days
is the morning of the 14th day, which equates to a 13.x day trial (x is the part of the day left over - if now is noon, then it's 13.5 day trial).
You would actually need to do this:
DateTime.now.midnight + 15.days
to get midnight on the 14th day.
For this reason I always prefer to use beginning_of_day, since that is 00:00:00. Using midnight can be misleading/misunderstood.
If you use it often consider install this gem to improve date parse:
https://github.com/mojombo/chronic
require 'chronic'
Chronic.parse('this 0:00')

Resources