--[[--------------------
	RTP.Date - Report Date Module.

	@module RPT.Date

	Usage Sample:

		1 - Now
			RPT.Date():now()

		2 - toDifferentTimezone - Convertir de UTC a un Timezone especifico.
			RPT.Date():toDifferentTimezone("fecha string", timezone "table")
			RPT.Date():toDifferentTimezone("fecha double", timezone "table")
			RPT.Date():toDifferentTimezone(nil, timezone "table") -- si es nil obtiene Now

----------------------]]

local lua_globaltimer = require "lua_globaltimer"
local os = require "os"

RPT = RPT or {}
local Date = {}
RPT.Date = {}

--[[
	Esta funcion se utiliza para logear todas las ejecuciones de las funciones de este LUA.
	Sirve para validar los valores retornados.

	Se habilita con la variable "m_enableLog" que por defecto se encuentra en false.
]]--
local m_enableLog = false
local function MyLog (...)
	if not m_enableLog then
		return
	end
	LogDebug(...)
end

--[[
	Funcion que crea una instancia de la "globaltimer".
	La realiza una unica vez, es decir si la Globatimer ya fue instanciada, no vuelve a instanciarla.
]]--
RPT.SetGlobalTimer = function(cluster)
	assert(cluster)
	MyLog("[RPT.Date:SetGlobalTimer] 1- Set global timer. cluster '%s', current globaltimer: %s.", cluster, Date.globaltimer)
	if not Date.globaltimer then
		Date.globaltimer = lua_globaltimer.LuaGlobalTimer(cluster)
	end
	MyLog("[RPT.Date:SetGlobalTimer] 2- current globaltimer: %s.", Date.globaltimer)
end

--[[
	Para poder utilizar las funciones de este LUA hay que invocar a esta funcón RPT.Date().
]]--
RPT.Date = function()
	return Date
end

--[[
	Funcion que retorna la fecha UTC actual en double.
]]--
Date.time = function(self)
	local t = self.globaltimer:GetTime()
	-- MyLog("[RPT.Date:time] GetTime() '%s'.", t)
	return t
end

--[[
	Funcion que retorna la fecha UTC actual en string.
]]--
Date.date = function(self)
	local t = self.globaltimer:GetHumanReadableTime()
	-- MyLog("[RPT.Date:time] GetHumanReadableTime() '%s'.", t)
	return t
end

--[[
	Funcion que retorna la fecha UTC actual en double.
	Idem a la funcion "time"
]]--
Date.now = function(self)
	local t = self:time()
	-- MyLog("[RPT.Date:now] now '%s'.", t)
	return t
end

--[[
	Funcion que retorna la fecha UTC actual en string.
	Recibe forma opcional el formato de la fecha a retornar.
]]--
Date.nowString = function(self, customFormat)
	local now = self:now()
	local nowString = self:toString(now, customFormat)
	-- MyLog("[RPT.Date:nowString] now '%s', nowString '%s', customFormat, nowString '%s'.", now, nowString, customFormat)
	return nowString
end

--[[
	Funcion que convierte una fecha string en double.
]]--
Date.timeFromString = function(self, stringDate)
	assert(type(stringDate) == "string")
	MyLog("[RPT.Date:timeFromString] a--> stringDate '%s' to convert.", stringDate)
	local timeDouble = self.globaltimer:GetTimeDoubleFromString(stringDate)
	MyLog("[RPT.Date:timeFromString] b- self.globaltimer:TimeDoubleFromString('%s') = '%s' converted.", stringDate, timeDouble)
	return timeDouble
end

--[[
	Funcion que convierte una fecha string en double.
	YYYY-MM-DD hh:mm:ss.000
	https://stackoverflow.com/questions/7960318/math-to-convert-seconds-since-1970-into-date-and-vice-versa
	No trajo mejoras de performance, la dejo por si sirve para algo
]]--
Date.standardTimeFromString = function(self, stringDate)
	local year, month, day, hour, min, sec, ms  = string.match(stringDate, "^(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+).(%d+)$")
	if not (year and month and day) then
		return false
	end

	year = tonumber(year)
	month = tonumber(month)
	day = tonumber(day)
	hour = tonumber(hour)
	min = tonumber(min)
	sec = tonumber(sec)
	ms = tonumber(ms)
	if month <= 2 then
		year = year - 1
	end
	local era = math.floor(year / 400)
    local yoe = year - era * 400
	if yoe < 0 then
		yoe = 0
	end
	local doy = math.floor((135 * (month + (month > 2 and -3 or 9)) + 2) / 5 + day - 1)
	local doe = math.floor(yoe * 365 + yoe/4 - yoe/100 + doy)
    local daysTimestamp = era * 146097 + doe - 719468
	local timestamp = ((daysTimestamp * 24 + hour) * 60 + min) * 60 + sec + (ms / 1000)
	return timestamp
end

--[[
	Funcion que convierte una fecha table en double y su representacion en string.
	La tabla de tipo fecha tiene que contener los atributos segun el ejemplo:
		{year = year, month = month, day = day, hour = hours, min = mins, sec = secs, ms = ms}
]]--
Date.timeFromTable = function(self, tableDate)
	assert(type(tableDate) == "table")

	local year = tonumber(tableDate.year)
	assert(type(year) == "number")

	local month = tonumber(tableDate.month)
	assert(type(month) == "number")

	local day = tonumber(tableDate.day)
	assert(type(day) == "number")

	local hour = tonumber(tableDate.hour)
	assert(type(hour) == "number")

	local min = tonumber(tableDate.min)
	assert(type(min) == "number")

	local sec = tonumber(tableDate.sec) or "00"
	local ms = tonumber(tableDate.ms) or "000"

	-- 2017-07-26 22:29:05.267
	local stringDate = ("%s-%s-%s %s:%s:%s.%s"):format(
		year, month, day, hour, min, sec, ms
	)

	local timeDouble = self:timeFromString(stringDate)
	local humanTimeString = self.globaltimer:GetHumanReadableTimeFromDouble(timeDouble)

	-- MyLog("[RPT.Date:timeFromTable] stringDate: '%s' --> timeDouble: '%s' -> humanTimeString: '%s'.", stringDate, timeDouble, humanTimeString)

	return timeDouble, humanTimeString
end

--[[
	Funcion que genera y devuelve un Time de tipo double.
		Recibe un parametro "time" que puede ser:
			1 - string = si es string lo convierte a double
			2 - table  = si es table lo convierte a double
			3 - nil    = si es nil retorna el double de la fecha actual
			4 - number = lo retorna como viene.
			5 - cualquier otro tipo falla.
]]--
Date.__makeTimeDouble = function(self, time)
	local timeDouble
	if not time then
		timeDouble = self:time()
	elseif type(time) == "string" then
		timeDouble = self:timeFromString(time)
	elseif type(time) == "table" then
		timeDouble = self:timeFromTable(time)
	else
		timeDouble = time
	end
	assert(type(timeDouble) == "number")
	return timeDouble
end

--[[
	Funcion que genera una objeto del sistema "date" y lo retorna en una tabla
	Por defecto es en UTC
]]--
Date.dateObject = function(self, time, notConvertToUTC)
	local timeDouble = self:__makeTimeDouble(time)
	local utcFormat = "!*t"
	local noUtcFormat = "*t"
	local isUTC = not notConvertToUTC
	local f = isUTC and utcFormat or noUtcFormat
	local dateObject = os.date(f, timeDouble)
	-- MyLog("[RPT.Date:dateObject] time '%s', timeDouble '%s' format: '%s' isUTC: '%s' dateObject: '%s'.", time, timeDouble, f, isUTC, json.encode(dateObject))
	return dateObject
end

--[[
	Funcion que retorna el mes de la fecha
]]--
Date.month = function(self, time)
	local dateObject = self:dateObject(time)
	local month = dateObject.month
	-- MyLog("[RPT.Date:month] month '%s'.", month)
	return month
end

--[[
	Funcion que retorna el dia de la fecha
]]--
Date.day = function(self, time)
	local dateObject = self:dateObject(time)
	local day = dateObject.day
	-- MyLog("[RPT.Date:day] day '%s'.", day)
	return day
end

--[[
	Funcion que retorna el año de la fecha
]]--
Date.dayOfYear = function(self, time)
	local dateObject = self:dateObject(time)
	local yday = dateObject.yday
	-- MyLog("[RPT.Date:dayOfYear] yday '%s'.", yday)
	return yday
end

--[[
	Funcion que retorna el dia de la semana
]]--
Date.dayOfWeek = function(self, time)
	local dateObject = self:dateObject(time)
	local wday = dateObject.wday
	-- MyLog("[RPT.Date:dayOfWeek] wday '%s'.", wday)
	return wday
end

--[[
	Funcion que retorna la hora de la fecha
]]--
Date.hour = function(self, time)
	local dateObject = self:dateObject(time)
	local hour = dateObject.hour
	-- MyLog("[RPT.Date:hour] hour '%s'.", hour)
	return hour
end

--[[
	Funcion que retorna los minutos de la fecha
]]--
Date.minute = function(self, time)
	local dateObject = self:dateObject(time)
	local min = dateObject.min
	-- MyLog("[RPT.Date:minute] min '%s'.", min)
	return min
end

--[[
	Funcion que retorna los segundos de la fecha
]]--
Date.second = function(self, time)
	local dateObject = self:dateObject(time)
	local sec = dateObject.sec
	-- MyLog("[RPT.Date:second] sec '%s'.", sec)
	return sec
end

--[[
	Funcion que retorna la hora de la fecha en forma militar.
	Ej:
		las 22:19 retorna 2219
]]--
Date.militaryTime = function(self, time)
	local dateObject = self:dateObject(time)
	local militaryTime = (100 * dateObject.hour) + dateObject.min
	-- MyLog("[RPT.Date:militaryTime] militaryTime '%s'.", militaryTime)
	return militaryTime
end

--[[
	Funcion que retorna los minutos de una hora dada.
	Ej:
		las 22:19 retorna 1339
]]--
Date.dayMinutes = function(self, time)
	local dateObject = self:dateObject(time)
	local minutes = (60 * dateObject.hour) + dateObject.min
	-- MyLog("[RPT.Date:dayMinutes] minutes '%s'.", minutes)
	return minutes
end

--[[
	Funcion que a partir de una fecha en UTC la convierte a un timezone determinado.
	Retorna su representación en string y en double.
]]--
Date.toDifferentTimezone = function(self, utcTime, timezone, customFormat)
	assert(type(timezone) == "table")
	assert(timezone.offset)

	local utcTimeDouble	= self:__makeTimeDouble(utcTime)

	-- MyLog("[RPT.Date:toDifferentTimezone] a - utcTimeDouble '%s', utcTimeString '%s' timezone '%s'.", utcTimeDouble, self.globaltimer:GetHumanReadableTimeFromDouble(utcTimeDouble), json.encode(timezone))

	local timezoneTimeDouble = self.globaltimer:GetTimeToDifferentTimeZoneFromDouble(utcTimeDouble, timezone)
	local timezoneTimeString

	if customFormat then
		timezoneTimeString = self:toString(timezoneTimeDouble, customFormat)
	else
		timezoneTimeString = self.globaltimer:GetHumanReadableTimeFromDouble(timezoneTimeDouble)
	end

	-- MyLog("[RPT.Date:toDifferentTimezone] b - timezoneTimeDouble '%s', timezoneTimeString '%s', customFormat: '%s'.", timezoneTimeDouble, timezoneTimeString, customFormat)

	return timezoneTimeString, timezoneTimeDouble
end

--[[
	Convierte el timestamp al timezone
]]--
Date.getTimeToDifferentTimeZone = function(self, utcTime, timezone)
	timezone.minutes = timezone.minutes or 0
	local offsetMinutes = timezone.offset * 60 + timezone.minutes + (timezone.dst and 60 or 0)
	return utcTime + offsetMinutes * 60
end

--[[
	Funcion que a partir de una fecha en UTC la convierte a un timezone determinado.
	Retorna su representación en string y en double.
]]--
Date.toDifferentTimezoneString = function(self, utcTime, timezone, customFormat)
	assert(type(timezone) == "table")
	assert(timezone.offset)

	-- MyLog("[RPT.Date:toDifferentTimezone] a - utcTime '%s', timezone '%s'.", utcTime, json.encode(timezone))

	if type(utcDate) == "string" then
		utcDate = self:timeFromString(utcDate)
	end

	local timezoneTimeDouble = self:getTimeToDifferentTimeZone(utcTime, timezone)
	local timezoneTimeString

	if customFormat then
		timezoneTimeString = self:toString(timezoneTimeDouble, customFormat)
	else
		timezoneTimeString = self.globaltimer:GetHumanReadableTimeFromDouble(timezoneTimeDouble)
	end

	-- MyLog("[RPT.Date:toDifferentTimezone] b - timezoneTimeDouble '%s', timezoneTimeString '%s', customFormat: '%s'.", timezoneTimeDouble, timezoneTimeString, customFormat)

	return timezoneTimeString, timezoneTimeDouble
end


--[[
	Funcion que retorna los ms de una fecha determianda.
]]--
Date.getMilliseconds = function(self, timeDouble)
	local int = math.floor(timeDouble)
	local dif = timeDouble - int
	local milliseconds = dif * 1000

	---- MyLog("[RPT.Date:getMilliseconds] - timeDouble '%s', int: '%s', dif: '%s', milliseconds '%s'.", timeDouble, int, dif, milliseconds)

	local dfm = milliseconds - math.floor(milliseconds)
	---- MyLog("[RPT.Date:getMilliseconds] - dfm '%s'.", dfm)

	if dfm > 0.5 then
		---- MyLog("[RPT.Date:getMilliseconds] icrementa en 1.")
		milliseconds = milliseconds + 1
	end

	---- MyLog("[RPT.Date:getMilliseconds] - timeDouble '%s', milliseconds '%s'.", timeDouble, milliseconds)
	return milliseconds
end

--[[
	Funcion que formatea a string un fecha determinada.
]]--
Date.toString = function(self, time, aFormat)
	-- MyLog("[RPT.Date:toString] a- time '%s', aFormat '%s'.", time, aFormat)
	local timeDouble = self:__makeTimeDouble(time)

	local custom = aFormat
	aFormat = aFormat or "!%Y-%m-%d %H:%M:%S"
	if aFormat:sub(1, 1) ~= "!" then
		aFormat = "!" .. aFormat
	end

	local formattedDate = os.date(aFormat, timeDouble)

	-- MyLog("[RPT.Date:toString] b- timeDouble '%s', aFormat '%s' -> formattedDate: '%s'.", timeDouble, aFormat, formattedDate)

	if custom then
		return formattedDate
	end

	local milliseconds = self:getMilliseconds(timeDouble)
	local formattedDate = formattedDate .. (".%03d"):format(milliseconds)

	-- MyLog("[RPT.Date:toString] c- timeDouble '%s', aFormat '%s' -> formattedDate: '%s', milliseconds: '%s'.", timeDouble, aFormat, formattedDate, milliseconds)

	return formattedDate
end

--[[
	Funcion que a partir de una fecha retorna la misma con hora, minutos, segundos con valores en 0.
	Ej:
		2017-07-26 22:19:14  -> 2017-07-26 00:00:00
]]--
Date.dayDate = function(self, timeDouble)
	local time = timeDouble or self:time()
	local formatDate = "%Y-%m-%d 00:00:00.000"
	local dayDate = self:toString(timeDouble, formatDate)
	local timeDouble = self:timeFromString(dayDate)
	return dayDate, timeDouble
end

--[[
	Funcion suma o resta dias a una fecha dada.
	Recibe una fecha y un tabla con los valores a incrementar.
	Ej. de la tabla:
		{days = 2, hours = 1, minutes = 3, seconds = 18}
		
		2017-07-26 22:19:14  -> 2017-07-28 23:22:32

		Como se puede ver a la fecha anterior le sumo 2 días, 1 hora, 3 minutos y 18 segundos.
]]--
Date.increase = function(self, time, incrementInfo)
	assert(type(incrementInfo) == "table")
	-- MyLog("[RPT.Date:increase] - incrementInfo '%s'.", json.encode(incrementInfo))
	assert(
		type(incrementInfo.days)    == "number" or
		type(incrementInfo.hours)   == "number" or
		type(incrementInfo.minutes) == "number" or
		type(incrementInfo.seconds) == "number"
	)

	local timeDouble = self:__makeTimeDouble(time)

	-- MyLog("[RPT.Date:increase] - source timeDouble '%s', source timeString '%s'.", timeDouble, self.gobaltimer:GetHumanReadableTimeFromDouble(timeDouble))

	local function MinsToSeconds (min)
		if not min then
			return 0
		end
		return min * 60
	end
	local function HoursToSeconds (hours)
		if not hours then
			return 0
		end
		local minutes = hours * 60
		return MinsToSeconds(minutes)
	end
	local function DaysToSeconds (days)
		if not days then
			return 0
		end
		local hours = days * 24
		return HoursToSeconds(hours)
	end

	local secondsByDays = DaysToSeconds(incrementInfo.days)
	-- MyLog("[RPT.Date:increase] - secondsByDays '%s', incrementInfo.days '%s'.", secondsByDays, incrementInfo.days)
	local secondsByHours = HoursToSeconds(incrementInfo.hours)
	-- MyLog("[RPT.Date:increase] - secondsByHours '%s', incrementInfo.hours '%s'.", secondsByHours, incrementInfo.hours)
	local secondsByMins = MinsToSeconds(incrementInfo.minutes)
	-- MyLog("[RPT.Date:increase] - secondsByMins '%s', incrementInfo.minutes '%s'.", secondsByMins, incrementInfo.minutes)

	local sencodsToIncrement = secondsByDays + secondsByHours + secondsByMins + (incrementInfo.seconds or 0)

	local newTimeDouble = AddSecondsTimeFromDouble(timeDouble, sencodsToIncrement)
	local newTimeString = self.globaltimer:GetHumanReadableTimeFromDouble(newTimeDouble)

	-- MyLog("[RPT.Date:increase] - (oldTimeDouble '%s', oldTimeString '%s') -> (newTimeDouble '%s', newTimeString '%s') -> se ha incrementado %s segundos.", timeDouble, self.globaltimer:GetHumanReadableTimeFromDouble(timeDouble), newTimeDouble, newTimeString, sencodsToIncrement)

	return newTimeDouble
end

--[[
	Funcion que tiene varios juegos de pruebas de todas las funciones que este LUA expone.

	Hace la comporativa con las invocaciones y los resutlados de sus pares con LuaOrm.Date.

	Ej de uso:
		RPT.Date():test(interactionID)

]]--
Date.test = function(self, interactionID)
	-- MyLog("---LUAORM-------------------------------------------")
	local timezone = {
		offset = -3,
		minutes = 0,
		dst = false
	}
		local now = LuaOrm.Date()
		local t = now:time()
	-- MyLog("1-- CANY -- LuaOrm.Date():time() = '%s'", t)
	
	local formatDate
	local fd1 = now:toString(formatDate)
	-- MyLog("1.01-- CANY -- now:toString(%s) = '%s'", formatDate or "", fd1)
	
	formatDate = "%Y-%m-%d %H:%M:%S"
	local fd1 = now:toString(formatDate)
	-- MyLog("1.02-- CANY -- now:toString(%s) = '%s'", formatDate or "", fd1)
	
	formatDate = "%Y-%m-%dT%H:%M:%S.000Z"
	local fd1 = now:toString(formatDate)
	-- MyLog("1.03-- CANY -- now:toString(%s) = '%s'", formatDate or "", fd1)
	
	formatDate = "%Y-%m-%dT%H:%M:%S+0000"
	local fd1 = now:toString(formatDate)
	-- MyLog("1.04-- CANY -- now:toString(%s) = '%s'", formatDate or "", fd1)
	
	local utcTime = UTCTime()
	-- MyLog("1.1-- CANY -- utcTime = '%s'", utcTime)
	local d = LuaOrm.Date(utcTime)
	-- MyLog("1.1-- CANY -- LuaOrm.Date(utcTime) = '%s'", d)
	local nowAtDest = d:toDifferentTimezone(timezone)
	-- MyLog("1.2-- CANY -- LuaOrm.Date(utcTime):toDifferentTimezone(timezone) = '%s'", nowAtDest)
	
	local dayDate = d:dayDate()
	-- MyLog("1.3-- CANY -- %s -> LuaOrm.Date():dayDate() = '%s'", d, dayDate)
	
	local interaction = GetInteraction(interactionID)
	
	---- MyLog("1.4-- CANY -- interactionID %s - '%s'", interactionID, json.encode(interaction))
	
	local ti1 = LuaOrm.Date(interaction.startTimestampReadable):toDifferentTimezone(timezone)
	
	-- MyLog("1.5-- CANY - LuaOrm.Date('%s'):toDifferentTimezone(%s)  -> '%s'", interaction.startTimestampReadable, json.encode(timezone), ti1)
	
	---- MyLog("1.4-- CANY -- interactionID %s - '%s'", interactionID, interaction)
	-- local isExpired = isInteractionExpired(interaction, 1)
	-- -- MyLog("1.5-- CANY -- interactionID %s - '%s'", interactionID, isExpired)
	
	
	local lastEventTimestampStr = interaction.lastEventTimestampStr
	-- MyLog("[RPT.isInteractionExpired -> LuaOrm.Date] 0.1 -interaction.lastEventTimestampStr %s", interaction.lastEventTimestampStr)
	local lastEventTimestamp = LuaOrm.Date(lastEventTimestampStr)
	-- MyLog("[RPT.isInteractionExpired -> LuaOrm.Date] 1 -lastEventTimestamp %s", lastEventTimestamp)
	
	local now11 = LuaOrm.Date()
	-- MyLog("[RPT.isInteractionExpired -> LuaOrm.Date] 2 -now %s", now11)
	local daysToIncrement = 2
	local lastWeek = LuaOrm.Date {year = now11:year(), month = now11:month(), day = (now11:day() - daysToIncrement), hour = 0}
	
	-- MyLog("[RPT.isInteractionExpired -> LuaOrm.Date] 3 - Se ha incrementado la fecha: -->  fecha '%s' + '%s' dias = '%s'", now11, daysToIncrement, lastWeek)
	
	local hasExpired = lastEventTimestamp:time() < lastWeek:time()
	
	-- MyLog("[RPT.isInteractionExpired -> LuaOrm.Date] 4 -%s < %s = %s", lastEventTimestamp:time(), lastWeek:time(), hasExpired)
	
	
	
	-- MyLog("--RPT.DATE--------------------------------------------")
	local now1 = RPT.Date()
	local t1 = now1:time()
	-- MyLog("2-- CANY -- RPT.Date:time() = '%s'", t1)
	
	local formatDate1
	local fd2 = RPT.Date():toString(nil, formatDate1)
	-- MyLog("2.01-- CANY -- RPT.Date:toString(%s) = '%s'", formatDate1 or "", fd2)
	
	local stringDate = fd2 -- "2020-12-09 16:20:34"
	local t3 = RPT.Date():timeFromString(stringDate)
	-- MyLog("2.01.1- CANY -- RPT.Date:timeFromString('%s') = '%s'", stringDate, t3)
	
	formatDate1 = "%Y-%m-%d %H:%M:%S"
	local fd2 = RPT.Date():toString(nil, formatDate1)
	-- MyLog("2.03-- CANY -- RPT.Date:toString(%s) = '%s'", formatDate1 or "", fd2)
	
	formatDate1 = "%Y-%m-%dT%H:%M:%S.000Z"
	local fd2 = RPT.Date():toString(nil, formatDate1)
	-- MyLog("2.04-- CANY -- RPT.Date:toString(%s) = '%s'", formatDate1 or "", fd2)
	
	formatDate1 = "%Y-%m-%dT%H:%M:%S+0000"
	local fd2 = RPT.Date():toString(nil, formatDate1)
	-- MyLog("2.05-- CANY -- RPT.Date:toString(%s) = '%s'", formatDate1 or "", fd2)
	
	local t2 = now1:date()
	-- MyLog("2.1-- CANY -- RPT.Date:date() = '%s'", t2)
	
	local nowAtDest = RPT.Date():toDifferentTimezone(nil, timezone)
	-- MyLog("2.2-- CANY -- RPT.Date:toDifferentTimezone(timezone) = '%s'", nowAtDest)
	
	local dayDate = RPT.Date():dayDate()
	-- MyLog("2.3-- CANY -- RPT.Date:dayDate() = '%s'", dayDate)
	
	local incrementedDate = RPT.Date():increase(nil, {hours = 0, minutes = 0, seconds = -3600})
	-- MyLog("2.4-- CANY -- RPT.Date:increase(nil,) = '%s'", incrementedDate)
	
	local timezoneStartTimestampReadable= RPT.Date():toDifferentTimezone(interaction.startTimestampReadable, timezone)
	-- MyLog("2.5-- CANY - RPT.Date interaction.startTimestampReadable '%s' -> timezoneStartTimestampReadable '%s'", interaction.startTimestampReadable, timezoneStartTimestampReadable)
	--
	 local lastEventTimestampStr = interaction.lastEventTimestampStr
	-- -- MyLog("[RPT.isInteractionExpired -> RPT.Date] 0.1 -interaction.lastEventTimestampStr %s", interaction.lastEventTimestampStr)
	-- local lastEventTimestamp = RPT.Date(lastEventTimestampStr)
	-- -- MyLog("[RPT.isInteractionExpired -> RPT.Date] 1 -lastEventTimestamp %s", lastEventTimestamp)
	
	 local nowString = RPT.Date():nowString()
	-- -- MyLog("[RPT.isInteractionExpired -> RPT.Date] 2 -now %s", now11)
	 local daysToIncrement = 2
	 local lastWeek = RPT.Date():increase(nowString, {days = daysToIncrement, hours = 0, minutes = 0, seconds = 0})
	
	 -- MyLog("[RPT.isInteractionExpired -> RPT.Date] 3 - Se ha incrementado la fecha: -->  fecha '%s' + '%s' dias = '%s' --> ", nowString, daysToIncrement, lastWeek)
	
	 local daysToIncrement = -2
	 local lastWeek = RPT.Date():increase(nowString, {days = daysToIncrement, hours = 0, minutes = 0, seconds = 0})
	
	 -- MyLog("[RPT.isInteractionExpired -> RPT.Date] 3 - Se ha decrementado la fecha: -->  fecha '%s' + '%s' dias = '%s' --> ", nowString, daysToIncrement, lastWeek)
	
	-- local hasExpired = lastEventTimestamp:time() < lastWeek:time()
	
	-- -- MyLog("[RPT.isInteractionExpired -> RPT.Date] 4 -%s < %s = %s", lastEventTimestamp:time(), lastWeek:time(), hasExpired)
	
	local lastWeek = RPT.Date():increase(nowString, {days = 0, hours = 5, minutes = 0, seconds = 0})
	
	local lastWeek = RPT.Date():increase(nowString, {days = 0, hours = 0, minutes = 5, seconds = 0})
	
	local lastWeek = RPT.Date():increase(nowString, {days = 0, hours = 0, minutes = 0, seconds = 5})


	local daysToIncrement = 11
	local lastEventTimestamp = LuaOrm.Date(lastEventTimestampStr)
	local now = LuaOrm.Date()
	local lastWeek = LuaOrm.Date {year = now:year(), month = now:month(), day = now:day() - daysToIncrement, hour = 0}
	older = lastEventTimestamp:time() < lastWeek:time()

	-- MyLog("[RPT.isInteractionExpired -> LuaOrm.Date] A - now: '%s', lastEventTime: '%s' (%s), lastWeek: '%s' (%s), daysToIncrement: '%s', expired: '%s'.",
	--			now, lastEventTimestamp:time(), lastEventTimestamp, lastWeek:time(), lastWeek, daysToIncrement, older)

	--local nowString = RPT.Date():nowString("%Y-%m-%d 00:00:00.000")
	local nowString = RPT.Date():dayDate()
	local timeDoubleLastWeek = RPT.Date():increase(nowString, {days = (daysToIncrement * -1)})
	local timeDoubleLastEvent = RPT.Date():timeFromString(lastEventTimestampStr)
	local older = timeDoubleLastEvent < timeDoubleLastWeek

	-- MyLog("[RPT.isInteractionExpired -> RPT.Date]     B - now: '%s', lastEventTime: '%s' (%s), lastWeek: '%s' (%s), daysToIncrement: '%s', expired: '%s'.",
	--		nowString,
	--		timeDoubleLastEvent, self.globaltimer:GetHumanReadableTimeFromDouble(timeDoubleLastEvent),
	--		timeDoubleLastWeek, self.globaltimer:GetHumanReadableTimeFromDouble(timeDoubleLastWeek),
	--		daysToIncrement, older)

	local now = LuaOrm.Date()
	local DOW = now:dayOfWeek()
	local hour = now:hour()
	local minute = now:minute()
	local militaryTime = 100 * hour + minute

	-- MyLog("[RPT.routing.GetOutgoingPackages -> LuaOrm.Date] ---> now: '%s', DOW: '%s', hour: '%s', minute: '%s', militaryTime: '%s'.", now, DOW, hour, minute, militaryTime)

	local now = RPT.Date():time()
	local DOW1 = RPT.Date():dayOfWeek(now)
	local hour1 = RPT.Date():hour(now)
	local minute1 = RPT.Date():minute(now)
	local militaryTime1 = RPT.Date():militaryTime(now)

	-- MyLog("[RPT.routing.GetOutgoingPackages -> RPT.Date] ---> now: '%s', DOW1: '%s', hour1: '%s', minute1: '%s', militaryTime1: '%s'.", RPT.Date():toString(now), DOW1, hour1, minute1, militaryTime1)

	RPT.Date():day()
	RPT.Date():dayOfYear()
	RPT.Date():dayOfWeek()
	RPT.Date():hour()
	RPT.Date():minute()
	RPT.Date():second()
	RPT.Date():militaryTime()

	-- MyLog("---")

	local startDateString = "2020-03-16 13:58:00.000"
	local startDate = LuaOrm.Date(startDateString)
	-- MyLog("[LuaOrm.Date] validationStartDate 1 -> startDate %s", startDate)
	local dayDate = startDate:dayDate()
	-- MyLog("[LuaOrm.Date] validationStartDate 2 -> dayDate %s", dayDate)
	local time = dayDate:time()
	-- MyLog("[LuaOrm.Date] validationStartDate 3 -> time %s", time)

	local dayDate, dayDateTime = RPT.Date():dayDate(startDateString)
	-- MyLog("[RPT.Date] validationStartDate 1 -> dayDate %s, dayDateTime %s", dayDate, dayDateTime)

	local nowDate = LuaOrm.Date()
	-- MyLog("[LuaOrm.Date] validationStartDate 1 -> nowDate %s", nowDate)
	local nowDayDate = nowDate:dayDate()
	-- MyLog("[LuaOrm.Date] validationStartDate 2 -> nowDayDate %s", nowDayDate)
	local nowTime = nowDayDate:time()
	-- MyLog("[LuaOrm.Date] validationStartDate 3 -> nowTime %s", nowTime)

	local nowDayDate, nowDayDateTime = RPT.Date():dayDate(nil) -- nil es now
	-- MyLog("[RPT.Date] validationStartDate 2 -> nowDayDate %s, nowDayDateTime %s", nowDayDate, nowDayDateTime)


	--local parsedTable = {year = "2020", month = 12, day = 11, hour = "22", min = 19, sec = 14, ms = 996}
	local parsedTable = {year = "2020", month = 01, day = 02, hour = "03", min = 04, sec = 05, ms = 06}

	local parsedDate = LuaOrm.Date(parsedTable)
	-- MyLog("[LuaOrm.Date] parsedDate: %s time: %s", parsedDate, parsedDate:time())

	local time, stringDate = RPT.Date():timeFromTable(parsedTable)
	-- MyLog("[RPT.Date] stringDate: %s time: %s", stringDate, time)

	local function GetTimeFromTable (dateString)
		local pattern = "(%d+)-(%d+)-(%d+)T(%d+):(%d+):(%d+)\+(%d+)"
		local year, month, day, hours, mins, secs, ms = dateString:match(pattern)
		local parsedTable = {year = year, month = month, day = day, hour = hours, min = mins, sec = secs}--, ms = ms}
		local time = RPT.Date():timeFromTable(parsedTable)
		-- A los MS los concateno de form manual, y no lo hago dentro de la clase
		if ms then
			time = time .. "." .. ms
		end
		LogDebug("[SOCIALNETWORKS:GetTimeFromTable] ---------------> dateString: '%s', time: '%s'.", dateString, time)
		return time
	end

	local socialNetworkDate = "2020-12-15T18:51:54+0000"
	GetTimeFromTable(socialNetworkDate)

	local socialNetworkDate = "2020-12-15T18:51:54+10"
	GetTimeFromTable(socialNetworkDate)

	-- MyLog("----------------------------------------------")
end
