Rest one month in a date golang - date

Im trying to rest a month in a date in golang i have this example for march an February:
date := time.Date(2023, time.March, 31, 0, 0, 0, 0, time.UTC)
then a make this:
period := date.AddDate(0, -1, -0)
but the program give me:
original date: 2023-03-31 00:00:00 +0000 UTC
date after rest: 2023-03-03 00:00:00 +0000 UTC
And I expect:
2023-02-28 00:00:00 +0000 UTC
at the same time I want that this rest work for every month dynamically.
Thanks.

Just as the automatically transform that comes with go annoys you, you could also take advantage of this.
The trick is how to get the number of days in the previous month.
// as there is no 0 day, it means the last day of the previous mouth
totDay := time.Date(y, m, 0, 0, 0, 0, 0, time.UTC).Day()
The complete code is as follows:
package main
import (
"fmt"
"time"
)
func previousMouth(t time.Time) time.Time {
y, m, d := t.Date()
curTotDay := time.Date(y, m+1, 0, 0, 0, 0, 0, time.UTC).Day()
totDay := time.Date(y, m, 0, 0, 0, 0, 0, time.UTC).Day()
if d == curTotDay {
d = totDay
}
return time.Date(y, m-1, d, 0, 0, 0, 0, time.UTC)
}
func main() {
date := time.Date(2023, time.March, 31, 0, 0, 0, 0, time.UTC)
fmt.Println(previousMouth(date))
}
Run it online: goplayground.

As others have mentioned in the comments, you cannot go back exactly one month from 31 March. You would end up at 31 February, but that date doesn't exist and is normalised to 3 March.
You can go back to the last day of the previous month, but you would get the same result if you started at 28 March, 29 March, 30 March or 31 March.
But if that is what you want, you can go back (or forward) any number of months, while clipping the day to remain within the number of days in that month.
func firstDayOfMonth(date time.Time) time.Time {
return date.AddDate(0, 0, -date.Day()+1)
}
func daysInMonth(date time.Time) int {
return date.AddDate(0, 1, -date.Day()).Day()
}
func AddMonthsClipped(date time.Time, months int) time.Time {
firstDate := firstDayOfMonth(date)
firstAdded := firstDate.AddDate(0, months, 0)
addDays, maxDays := date.Day(), daysInMonth(firstAdded)
if addDays > maxDays {
addDays = maxDays
}
return firstAdded.AddDate(0, 0, addDays-1)
}
func main() {
date := time.Date(2023, time.March, 31, 0, 0, 0, 0, time.UTC)
fmt.Println(AddMonthsClipped(date, -1))
}
Go Playground: https://go.dev/play/p/JEihMdM0CHe

I found the answer:
package main
import (
"fmt"
"time"
)
func main() {
date := time.Date(2023, time.March, 31, 0, 0, 0, 0, time.UTC)
year, month, _ := date.Date()
endOfLastMonth := time.Date(year, month, 0, 0, 0, 0, 0, date.Location())
fmt.Println("This month: ", date)
fmt.Println("Lasth Month: ", endOfLastMonth)
}
Here the playground: https://go.dev/play/p/iTDFgtdOT9y
After working and working with the date, i made this. Thanks you all

Related

GoLang's time.Date does not throw error for days beyond valid days in a month

I am trying to construct a GoLang time.Date() instance from the input I get; something like:
time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
Where 'year' 'month' and 'day' are read from a file.
It works fine for most of the cases, however if I pass "2000-01-32" it automatically interprets as "2000-02-01" Example in The Go Playground.
Is there a way to force returning error instead of carry over the day in a case like abovr?
Thanks.
Not directly but you can compare parsed value to given parameters. Unless normalized, they should be same.
func parse(year, month, day int) (time.Time, bool) {
t := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
y, m, d := t.Date()
return t, y == year && int(m) == month && d == day
}
In action: https://play.golang.org/p/UJYszuyJwnx

30 Min Time Increments not working in Swift

I am having issues getting my code to work. I am trying to create 30 minutes slots in Swift, but it seems to randomly jump an hour every so often. See code below:
let calendar = Calendar.current
var hour = 07
var hour2 = 07
var minute = 0
var timeLoop = 1
var startDate = calendar.date(bySettingHour: hour, minute: 0, second: 0, of: editedDate)
var endDate = calendar.date(bySettingHour: hour2, minute: 0, second: 0, of: editedDate)
repeat {
if(timeLoop % 2 == 0){
startDate = calendar.date(bySettingHour: hour2, minute: 30, second: 0, of: editedDate)
endDate = calendar.date(bySettingHour: hour, minute: 0, second: 0, of: editedDate)
}
else {
startDate = calendar.date(bySettingHour: hour2, minute: 0, second: 0, of: editedDate)
endDate = calendar.date(bySettingHour: hour2, minute: 30, second: 0, of: editedDate)
}
if (timeLoop == 1) {
startDate = calendar.date(bySettingHour: hour, minute: 0, second: 0, of: editedDate)
endDate = calendar.date(bySettingHour: hour, minute: 30, second: 0, of: editedDate)
}
let eventDate = EventDate()
eventDate.startDate = startDate!
eventDate.endDate = endDate!
self.suggestedDates.append(eventDate)
self.suggestedDates.sort(by: {$0.startDate < $1.startDate}) //Recheck this
//Only need to add this once for day purposes
if (hour == 07) {
self.allDayDates.append(eventDate)
self.allDayDates.sort(by: {$0.startDate < $1.startDate}) //Recheck this
}
//update hours
hour2 = hour
hour += 1
timeLoop += 1
} while hour <= 21
This gives the following results
07:00 - 07:30,
07:30 - 08:00,
08:00 - 08:30,
09:30 - 10:00,
10:00 - 10:30,
11:30 - 12:00,
12:00 - 12:30,
13:30 - 14:00,
As you can see theres a jump from 10:30 to 11:30.
Your code does not give enough idea of what you are trying to do.
However to get the time slots you can do something like this:
let calendar = Calendar.current
let startHour = 07 // Hour from where you want to start the slots
var hourCounter = 07 // Hour counter for looping
let slotDuration = 30 // Constant for duration of slots
let editedDate = Date() // The selected date, as per your code
// Create the start date by setting hour value to the `startHour` of `editedDate`
var startDate = calendar.date(bySettingHour: startHour, minute: 0, second: 0, of: editedDate)
// Assign the same value to endDate as the initial value
var endDate = startDate
repeat {
// Assign the end date to the start date,
// This will get you the slot start duration from earlier slot's end date
// For example,
// If this is the starting slot,
// then the startDate and endDate will be same, as per above code.
// If this is any subsequent slot,
// then the slot should start from the last slot's endDate.
// i.e. if previous slot was 01:30 - 2:00,
// then current slot should start from 2:00.
startDate = endDate
if let date = startDate {
// Get the new endDate by adding your slot duration to the startDate
endDate = calendar.date(byAdding: .minute, value: slotDuration, to: date)
}
// ...
// Do whatever you want to do with these slot values here...
// ...
// Increment the counter for looping
hourCounter += 1
} while hourCounter <= 21
The code generates time slots based on the slot duration. You can change the slotDuration to any desired value (in minute), and it will generate slots accordingly. Try changing it from 30 to 15 and see the results.

Server Hour considering another TZ as reference

I am trying to trigger a worker at certain hour. The thing is that I need to know what is the relative hour of the server for that hour. Clients want to trigger the worker at 8pm everyday in Los Angeles Time, so I have to make it the enough dynamic that it takes the server hour, calculate what is the equivalent for that hour in Los Angeles. I am also using carbon, but is there any built-in function for that? Or is there any know routine to deal with it?
time.LoadLocation and time.In are the two functions you need. The below code is copied and modified from time.LoadLocation example:
func main() {
location, err := time.LoadLocation("America/Los_Angeles")
if err != nil {
panic(err)
}
timeInUTC := time.Date(2018, 8, 30, 12, 0, 0, 0, time.UTC)
fmt.Println(timeInUTC.In(location))
now := time.Now()
timeThere := time.Date(now.Year(), now.Month(), now.Day(), 8, 0, 0, 0, location)
timeHere := timeThere.In(time.Now().Location())
fmt.Println(timeHere)
}

Output dates based on an array

Need Help. I have an associative array which has the days of the week. I know very little about arrays. Each day has a 1 or 0 in the array below. I am trying to output dates and use them to generate tasks. I'm sure can this be done easily, but I lack the experience.
I want to output only dates which have 1's as shown in the array below.
The first task is due in 4 days.
I need to view dates up to 3 days ahead, so if today is Tuesday, and start is on Friday, then the Friday task date won't appear until Wednesday.
Today := A_now
WeekDays_Array := {Sun: 0, Mon: 0, Tue: 1, Wed: 0, Thu: 1, Fri: 1, Sat: 0}
I am pretty sure this is most of it. The suggestion to use the array above made the most sense.
The script uses Wkday (which is A_Now) as the start day but I think that can be changed by substituting it for a specific start day
PastDue := []
DueBy := []
;~ Weekday_Array := {Sunday: 0, Monday: 0, Tuesday: 1, Wednesday: 0, Thursday: 1, Friday: 1, Saturday: 0}
Weekday_Array := [1,1,1,1,1,1,1] ;Represents Sun-Saturday
AssignTask:
FormatTime, WkDay, MyTime, WDay
For i, value in Weekday_Array{
DueDate =
if (i > WkDay && Value = 1){
x++
DueDate += (x), days
FormatTime, DueDate, % DueDate, MM/dd/yy
DueBy.InsertAt(i,DueDate)
}
if (i = WkDay && Value = 1){
FormatTime, DueDate, % A_Now, MM/dd/yy
DueBy.InsertAt(i,DueDate)
}
if (i < WkDay && Value = 1){
y--
Pastdate =
PastDate += (y) , days
NewDate := PastDate
NewDate += 7, days
FormatTime, PastDate, % PastDate, MM/dd/yy
FormatTime, NewDate, % NewDate, MM/dd/yy
PastDue.InsertAt(i,PastDate)
DueBy.insertAt(i,NewDate)
}
}
For i, PastDue in PastDue
PastDueDates .= PastDue "`n"
Sort, PastDueDates
PastDueDates := "Past due dates so far this week `n`n" PastDueDates
MsgBox, 0x1000,, % PastDueDates
For i, DueDate in DueBy
DueDates .= DueDate "`n"
Sort, DueDates
DueDates := "All upcoming due dates based criteria `n`n" DueDates
MsgBox, 0x1000,, % DueDates
sort, DueDates
FormatTime, xDay1, % A_Now, MM/dd/yy
xDay2 += 1, days
FormatTime, xDay2, % xDay2, MM/dd/yy
xDay3 += 2, days
FormatTime, xDay3, % xDay3, MM/dd/yy
For i, DueDate in DueBy{
if (DueDate = xDay1 || DueDate = xDay2 || DueDate = xDay3)
XDays .= DueDate "`n"
}
xDays := "Only view the next 3 days from today `n`n" xDays
MsgBox, 0x1000,, % xDays
;~ return
*esc::
ExitApp
return

Swift timezones with winter/summer times

I am working on a world clock, and i have gotten the times for various countries as so:
let date = NSDate();
var beltz = NSDateFormatter();
beltz.dateFormat = "HH:mm";
beltz.timeZone = NSTimeZone(name: "Europe/Brussels")
let belTzStr = beltz.stringFromDate(date);
println(belTzStr) //<-- correct time
My question is when summer/winter times adjust +- 1 hour, will this adjustment be reflected in the code by NSTimeZone? If not, how do i achieve this?
Consider this modified code:
let cal = NSCalendar.currentCalendar()
cal.timeZone = NSTimeZone(name: "America/Phoenix")!
let date = cal.dateWithEra(1, year: 2015, month: 12, day: 24, hour: 16, minute: 0, second: 0, nanosecond: 0)!
//date = NSDate();
var beltz = NSDateFormatter();
beltz.dateFormat = "dd MMMM HH:mm zzzz";
beltz.timeZone = NSTimeZone(name: "Europe/Brussels")
let belTzStr = beltz.stringFromDate(date);
print(belTzStr) //<-- correct time
I modified your code to add time as Phoenix AZ, which does not use summer time and added some extra formatting, especially the TZ to the printed data.
Now, if you use December (no DST in either region)
let date = cal.dateWithEra(1, year: 2015, month: 12, day: 24, hour: 16, minute: 0, second: 0, nanosecond: 0)!,
you get
25 December 00:00 Central European Standard Time
and if you use July (DST in EU)
let date = cal.dateWithEra(1, year: 2015, month: 7, day: 24, hour: 16, minute: 0, second: 0, nanosecond: 0)!,
you get
25 July 01:00 Central European Summer Time
So yes, it adjusts the TZ appropriately.