Hey there!
I am have just completed my daily item shop and all the features of it, using this amazing tutorial by @rek_kie. It works great and I love it except for one thing. The video will explain:
https://www.wevideo.com/view/2159133106
Here is the serverscript:
local syncedtime = require(game.ServerStorage.SyncedTime)
local UpdateFunction = game.ReplicatedStorage.UpdateRemoteFunction
local updateTimerEvent = game.ReplicatedStorage:WaitForChild("ShopTimeUpdate")
syncedtime.init()
local function toHMS(s)
	return string.format("%02i:%02i:%02i", s/60^2, s/60%60, s%60)
end
local CommonItems = {
	"RthroAnim";
	"GreenParticleTrail";
	"CloudParticleTrail"; --
	"CheckMarkParticleTrail";
	"HeartParticleTrail";
	"QuestionMarkParticleTrail";
	"SunParticleTrail";
	"SpiderWebParticleTrail"
}
local UncommonItems = {
	"RobotAnim";
	"OldSchoolAnim"; --
	"StylishAnim";
	"BlueParticleTrail";
	"CrossMarkParticleTrail";
	"WaterParticleTrail";
	"ClubParticleTrail";
	"MoonParticleTrail"
}
local RareItems = {
	"ToyAnim";
	"BubblyAnim";
	"ElderAnim";
	"CartoonyAnim";
	"SuperHeroAnim";
	"MageAnim"; --
	"YellowParticleTrail";
	"TornadoParticleTrail"
}
local VeryRareItems = {
	"KnightAnim";
	"ZombieAnim"; --
	"AstronautAnim";
	"WerewolfAnim";
	"VampireAnim";
	"OrangeParticleTrail"; --
	"SpadeParticleTrail";
	"RockParticleTrail"
}
local EpicItems = {
	"PirateAnim";
	"NinjaAnim"; --
	"RedParticleTrail";
	"ExclaimationMarkParticleTrail";
	"DiamondParticleTrail";
	"FireParticleTrail"; --
	"CometParticleTrail";
	"MusicNoteParticleTrail"
}
local LegendaryItems = {
	"LevitationAnim";
	"PurpleParticleTrail";
	"StarParticleTrail";
	"LightningParticleTrail"; --
	"PresentParticleTrail";
	"CycloneParticleTrail"; --
	"SnowflakeParticleTrail"; --
	"ExplosionParticleTrail"
}
local weights = {
	Common = 100,
	Uncommon = 60,
	Rare = 32,
	VeryRare = 15,
	Epic = 5,
	Legendary = 1
}
function getAvailableItems(day, numberofitems)
	local rng = Random.new(day)
	local shopItems = {}
	
	local function shallowCopy(original)
		local copy = {}
		for key, value in pairs(original) do
			copy[key] = value
		end
		return copy
	end
	
	local function Generate()
		local shopitem = nil 
		local returnedRarity = nil
		
		local function GenerateWeightedItem()
			local rarity = nil
			local weightNumber = rng:NextNumber(0, 100)
			
			local weightitem = nil
			
			if weightNumber < weights.Legendary then
				print("Legendary")
				weightitem = LegendaryItems[rng:NextInteger(1, #LegendaryItems)]
				rarity = LegendaryItems
			elseif weightNumber < weights.Epic then
				print("Epic")
				weightitem = EpicItems[rng:NextInteger(1, #EpicItems)]
				rarity = EpicItems
			elseif weightNumber < weights.VeryRare then
				print("Very Rare")
				weightitem = VeryRareItems[rng:NextInteger(1, #VeryRareItems)]
				rarity = VeryRareItems
			elseif weightNumber < weights.Rare then
				print("Rare")
				weightitem = RareItems[rng:NextInteger(1, #RareItems)]
				rarity = RareItems
			elseif weightNumber < weights.Uncommon then
				print("Uncommon")
				weightitem = UncommonItems[rng:NextInteger(1, #UncommonItems)]
				rarity = UncommonItems
			elseif weightNumber < weights.Common then
				print("Common")
				weightitem = CommonItems[rng:NextInteger(1, #CommonItems)]
				rarity = CommonItems
			end
			
			return weightitem, rarity
		end
		
		shopitem, returnedRarity = GenerateWeightedItem()
		local itemtablecopy = shallowCopy(returnedRarity)
		
		for i, item in pairs(shopItems) do
			local duplicate = table.find(shopItems, shopitem)
			
			if duplicate then
				print("Respinning...")
				for number, v in pairs(itemtablecopy) do
					for i = 1,#shopItems do
						if v == shopItems[i] then
							table.remove(itemtablecopy, number)
						end
					end
				end
				repeat
					shopitem = itemtablecopy[rng:NextInteger(1, #itemtablecopy)]
				until shopitem ~= item
			end
		end
		table.insert(shopItems, shopitem)
	end
	
	repeat
		Generate()
	until #shopItems >= numberofitems
	
	return shopItems
end
local currentDay = nil
local currentShopItems = {}
local hourOffset = -3
local offset = (60 * 60 * hourOffset)
function UpdateShop()
	print("CAME THROUGH")
	return currentShopItems
end
UpdateFunction.OnServerInvoke = UpdateShop
while true do
	local day = math.floor((syncedtime.time() + offset) / (60 * 60 * 24))
	local t = (math.floor(syncedtime.time())) - offset
	local daypass = t % 86400
	local timeleft = 86400 - daypass
	local timeleftstring = toHMS(timeleft)
	
	local sentence = ("Time till shop resets: " .. timeleftstring)
	
	if day ~= currentDay then
		currentDay = day
		currentShopItems = getAvailableItems(day, 6)
		print("Today's Items: " .. table.concat(currentShopItems, ", "))
	end
	updateTimerEvent:FireAllClients(sentence)
	wait(1)
end
And here is the Local Script:
local player = game.Players.LocalPlayer
local UpdateFunction = game.ReplicatedStorage.UpdateRemoteFunction
local Items = require(game.ReplicatedStorage:WaitForChild("Items"))
boughtRequest = game.ReplicatedStorage:WaitForChild("BoughtRequest")
local WhatImage = "BuyImage"
local WhatPrice = "BuyPrice"
while true do
	wait(5)
	bought = boughtRequest:InvokeServer()
	local itemTable = UpdateFunction:InvokeServer()
	for i, button in ipairs(script.Parent.Items:GetChildren()) do
		if button.Buy.Value == false then
			local which = itemTable[i]
			button.Item.Value = which
			button.BackgroundColor3 = Items.Items[which].color
			button.Text = Items.Items[which].name
			button.IType.Value = Items.Items[which].class
			local image = script.Parent.ItemImages:FindFirstChild(WhatImage .. i)
			image.Image = "rbxassetid://" .. Items.Items[which].imageID
			if which == "GreenParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(0, 255, 0)
			elseif which == "BlueParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(0, 170, 255)
			elseif which == "YellowParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(255, 255, 0)
			elseif which == "OrangeParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(255, 170, 0)
			elseif which == "RedParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(255, 0, 0)
			elseif which == "PurpleParticleTrail" then
				image.ImageColor3 = Color3.fromRGB(170, 0, 255)
			elseif which == "OldSchoolAnim" then
				image.ImageColor3 = Color3.fromRGB(170, 0, 255)
			end
			local price = script.Parent.ItemPrices:FindFirstChild(WhatPrice .. i)
			price.Text = "Price: " .. Items.Items[which].price .. " Points"
			for k, v in pairs(bought) do
				--change the button color and text depending on the item we purchased
				if button.Buy.Value == false then
					if button.Item.Value == v then
						if button.IType == "Trail" then
							button.Text = button.Text .. " (Owned)"
						elseif button.IType == "Anim" then
							button.Text = button.Text .. " (Owned)"
						else
							button.Text = button.Text .. " (Owned)"
						end
					end
				end
			end 
		end	
	end
end 
If this helps here is the time module
local monthStrMap = {
	Jan=1,
	Feb=2,
	Mar=3,
	Apr=4,
	May=5,
	Jun=6,
	Jul=7,
	Aug=8,
	Sep=9,
	Oct=10,
	Nov=11,
	Dec=12
}
local HttpService = game:GetService("HttpService")
local function RFC2616DateStringToUnixTimestamp(dateStr)
	local day, monthStr, year, hour, min, sec = dateStr:match(".*, (.*) (.*) (.*) (.*):(.*):(.*) .*")
	local month = monthStrMap[monthStr]
	local date = {
		day=day,
		month=month,
		year=year,
		hour=hour,
		min=min,
		sec=sec
	}
	
	return os.time(date)
end
local isInited = false
local originTime = nil
local responseTime = nil
local responseDelay = nil
local function inited()
	return isInited
end
local function init()
	if not isInited then
		local ok = pcall(function()
			local requestTime = tick()
			local response = HttpService:RequestAsync({Url="http://google.com"}) 
			local dateStr = response.Headers.date
			originTime = RFC2616DateStringToUnixTimestamp(dateStr)
			responseTime = tick()
			-- Estimate the response delay due to latency to be half the rtt time
			responseDelay = (responseTime-requestTime)/2
		end)
		if not ok then
			warn("Cannot get time from google.com. Make sure that http requests are enabled!")
			originTime = os.time()
			responseTime = tick()
			responseDelay = 0
		end
		
		isInited = true
	end
end
local function time()
	if not isInited then
		init()
	end
	
	return originTime + tick()-responseTime - responseDelay
end
return {
	inited=inited,
	init=init,
	time=time
}
I am not really sure how it is possible for the time and the actual updating to be at separate times, but maybe it has something to do with the serverscript with the
if day ~= currentDay then
But I don’t know, does anyone have any ideas?
This code seems semi complicated, but it is probably easy for some of you, but we shall see!
