Skip to content

Instantly share code, notes, and snippets.

@alexyslozada
Last active March 13, 2021 16:20
Show Gist options
  • Save alexyslozada/f086dc1c8017732f034f6f4625fc64c5 to your computer and use it in GitHub Desktop.
Save alexyslozada/f086dc1c8017732f034f6f4625fc64c5 to your computer and use it in GitHub Desktop.
Calcula el último día hábil de acuerdo a los dos últimos digitos de un nit
// Este archivo me permite generar el SQL que se inserta en la tabla de social_security_date
// OJO: debe revisarse los festivos del año.
package social_security_date
import (
"fmt"
"log"
"sort"
"time"
)
const (
layoutISO = "2006-01-02"
)
var lastDayWithDigits = map[uint8][2]string{
2: [...]string{"00", "07"},
3: [...]string{"08", "14"},
4: [...]string{"15", "21"},
5: [...]string{"22", "28"},
6: [...]string{"29", "35"},
7: [...]string{"36", "42"},
8: [...]string{"43", "49"},
9: [...]string{"50", "56"},
10: [...]string{"57", "63"},
11: [...]string{"64", "69"},
12: [...]string{"70", "75"},
13: [...]string{"76", "81"},
14: [...]string{"82", "87"},
15: [...]string{"88", "93"},
16: [...]string{"94", "99"},
}
var holidays = []time.Time{
parseDate("2021-01-01"),
parseDate("2021-01-11"),
parseDate("2021-03-22"),
parseDate("2021-04-01"),
parseDate("2021-04-02"),
parseDate("2021-05-01"),
parseDate("2021-05-17"),
parseDate("2021-06-07"),
parseDate("2021-06-14"),
parseDate("2021-07-05"),
parseDate("2021-07-20"),
parseDate("2021-08-07"),
parseDate("2021-08-16"),
parseDate("2021-10-18"),
parseDate("2021-11-01"),
parseDate("2021-11-15"),
parseDate("2021-12-08"),
parseDate("2021-12-25"),
}
func GetLastBusinessDay(year, month int) {
date := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
keys := make([]int, 0, len(lastDayWithDigits))
for k := range lastDayWithDigits {
keys = append(keys, int(k))
}
sort.Ints(keys)
fmt.Println("INSERT INTO social_security_dates (last_two_digits_begins, last_two_digits_ends, business_day, year_date, month_date, last_date) VALUES ")
for _, k := range keys {
fmt.Print("(")
fmt.Printf(`'%s',`, lastDayWithDigits[uint8(k)][0])
fmt.Printf(`'%s',`, lastDayWithDigits[uint8(k)][1])
fmt.Printf(`%d,`, k)
fmt.Printf("%d, %d,", year, month)
fmt.Printf("'%s'", lastBusinessDay(date, uint8(k), []time.Weekday{time.Saturday, time.Sunday}, holidays).Format(layoutISO))
fmt.Println("),")
}
fmt.Println(";")
}
func parseDate(date string) time.Time {
r, err := time.Parse(layoutISO, date)
if err != nil {
log.Fatalf("parseDate(): no se pudo convertir la fecha: %v", err)
}
return r
}
func lastBusinessDay(firstDayOfMonth time.Time, days uint8, daysOff []time.Weekday, holidays []time.Time) time.Time {
countNonWorkingDays := nonWorkingDays(firstDayOfMonth, days, daysOff, holidays)
return addDays(firstDayOfMonth, countNonWorkingDays+days-1)
}
func nonWorkingDays(currDate time.Time, days uint8, daysOff []time.Weekday, holidays []time.Time) uint8 {
var nonWorkingDays uint8
currDate = removeDays(currDate, 1)
for days > 0 {
currDate = addDays(currDate, 1)
if dayIsDayOff(currDate.Weekday(), daysOff) || daysIsHoliday(currDate, holidays) {
nonWorkingDays++
continue
}
days--
}
return nonWorkingDays
}
// dayIsDayOff identifica si el día es dia de descanso
func dayIsDayOff(day time.Weekday, days []time.Weekday) bool {
for _, v := range days {
if day == v {
return true
}
}
return false
}
// daysIsHoliday identifica se el día es festivo
func daysIsHoliday(day time.Time, holidays []time.Time) bool {
for _, v := range holidays {
if day.Equal(v) {
return true
}
}
return false
}
// addDays agrega días a una fecha y retorna el resultado
func addDays(date time.Time, days uint8) time.Time {
return date.Add(time.Hour * 24 * time.Duration(days))
}
// removeDays quita días a una fecha y retorna el resultado
func removeDays(date time.Time, days int) time.Time {
return date.Add(time.Hour * 24 * -time.Duration(days))
}
package main
import (
"time"
)
func LastBusinessDay(firstDayOfMonth time.Time, days uint8, daysOff []time.Weekday, holidays []time.Time) time.Time {
countNonWorkingDays := nonWorkingDays(firstDayOfMonth, days, daysOff, holidays)
return addDays(firstDayOfMonth, countNonWorkingDays+days-1)
}
func nonWorkingDays(currDate time.Time, days uint8, daysOff []time.Weekday, holidays []time.Time) uint8 {
var nonWorkingDays uint8
currDate = removeDays(currDate, 1)
for days > 0 {
currDate = addDays(currDate, 1)
if dayIsDayOff(currDate.Weekday(), daysOff) || daysIsHoliday(currDate, holidays) {
nonWorkingDays++
continue
}
days--
}
return nonWorkingDays
}
// dayIsDayOff identifica si el día es dia de descanso
func dayIsDayOff(day time.Weekday, days []time.Weekday) bool {
for _, v := range days {
if day == v {
return true
}
}
return false
}
// daysIsHoliday identifica se el día es festivo
func daysIsHoliday(day time.Time, holidays []time.Time) bool {
for _, v := range holidays {
if day.Equal(v) {
return true
}
}
return false
}
// addDays agrega días a una fecha y retorna el resultado
func addDays(date time.Time, days uint8) time.Time {
return date.Add(time.Hour * 24 * time.Duration(days))
}
// removeDays quita días a una fecha y retorna el resultado
func removeDays(date time.Time, days int) time.Time {
return date.Add(time.Hour * 24 * -time.Duration(days))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment