ISO Dates from API to Countdown

Introduction
I am creating a script which receives a JSON table from an API using GetAsync, and creates a countdown from the start time information on the API to the end time. In this table it includes ISO dates as to when the event is going to start and when the event is going to end, for example “2021-06-29T14:38Z” representing 29-06-2021 at 14:38PM (in UTC)


--Services
local HttpService = game:GetService("HttpService")
local Endpoint = "http://worldclockapi.com/api/json/utc/now"

--Directories
local TimerTag = game.workspace.APITest:WaitForChild("TimerTag")


--Pcall Function incase request fails, GetAsync for retrieving data of next/current Event from API
--local Success = pcall(function()
local GetAsync = HttpService:GetAsync(Endpoint, false)
local DecodeResponse = HttpService:JSONDecode(GetAsync)

--"From" Current Event
local FromISODate = DateTime.fromIsoDate("2021-06-29T14:38Z") -- Insert ISO format date from API
local CurrentEvent = FromISODate:ToUniversalTime()
local CurrentTime = os.time({
   year=CurrentEvent["Year"],
   month=CurrentEvent["Month"],
   day=CurrentEvent["Day"],
   hour=CurrentEvent["Hour"], 
   min=CurrentEvent["Minute"], 
   sec=CurrentEvent["Second"]
})


--"To" End of Event
local ToISODate = DateTime.fromIsoDate("2021-06-29T11:03Z") -- Insert ISO format date from API
local EndEvent = ToISODate:ToUniversalTime()
local EndTime = os.time({
   year=EndEvent["Year"],
   month=EndEvent["Month"],
   day=EndEvent["Day"],
   hour=EndEvent["Hour"], 
   min=EndEvent["Minute"], 
   sec=EndEvent["Second"]
})


local StopCountdown = script.Parent.StopCountdown -- switches between not shown timer and shown timer


local function BackendTimer()
   while StopCountdown.Value == false do
   	wait(1)
   	local CountdownStart = CurrentTime - tick()
   	local StartDays = math.floor((CountdownStart / 60 / 60 / 24) % (365 + 0.2425)) 
   	local StartHours = math.floor((CountdownStart / 60 / 60) % 24) 
   	local StartMinutes = math.floor((CountdownStart / 60) % 60) 
   	local StartSeconds = math.floor(CountdownStart % 60) 
   	print(StartDays..":"..StartHours..":"..StartMinutes..":"..StartSeconds)
   	if StartDays == 0 and StartHours == 0 and StartMinutes == 0 and StartSeconds == 0 then
   		StopCountdown.Value = true
   	end
   end
end


local function EventTimer()
   while StopCountdown.Value == true do
   	wait(1)
   	local CountdownEnd = EndTime - tick()
   	local EndDays = math.floor((CountdownEnd / 60 / 60 / 24) % (365 + 0.2425)) 
   	local EndHours = math.floor((CountdownEnd / 60 / 60) % 24) 
   	local EndMinutes = math.floor((CountdownEnd / 60) % 60) 
   	local EndSeconds = math.floor(CountdownEnd % 60) 
   	print(EndDays..":"..EndHours..":"..EndMinutes..":"..EndSeconds)
   	TimerTag.Days.Days.Text = EndDays
   	TimerTag.Hours.Hours.Text = EndHours
   	TimerTag.Minutes.Minutes.Text = EndMinutes
   	TimerTag.Seconds.Seconds.Text = EndSeconds
   	if EndDays == 0 and EndHours == 0 and EndMinutes == 0 and EndSeconds == 0 then
   		StopCountdown.Value = false
   	end
   	if StopCountdown.Value == false then
   		EndDays = 0
   		EndHours = 0
   		EndMinutes = 0
   		EndSeconds = 0
   		BackendTimer()
   	end
   end
end

BackendTimer()
EventTimer()


What does this code do?
This code basically converts the given ISO date into UTC format which returns a table using ToUniversalTime() then converts the table to seconds using os.time() (I did this because the countdown seemed easier at the time converting and functioning with seconds) it then takes that information and converts it to Days, Hours, Minutes, Seconds etc. for the countdown (At this moment the countdown uses the current time you want to countdown to minus tick() and then converts from there. At this moment in time, i’m not worried about the information coming from the API as I know how to implement that into the script so I just used a random ISO date for now.

What issue do you have?
My issue is that once the countdown reaches 0 it continues throughout until the next year when the server restarts and it’s ran again, because it’s using a Unix Timestamp and the date that has been given has already passed. I want it to stop until the API sends further information on when the event start/ends or at least when the ISO date changes, and what is the most efficient way of at least laying out this code? I don’t expect you to write out the code, I’m just curious because it probably isn’t the way I’m doing it. This does function, it just doesn’t feel efficient enough.

Thanks for your time.

2 Likes