Is there a way to run a task each day at a 8:00 AM in vibed? - d

I'm trying to run a task each day at 8:00 AM in a vibe.d web app.
For the moment, I use the setTimer function with the periodic parameter to true. But this way, I can't control exactly the hour at which the task will be triggered. Is there an easy way to do this in vibed ?

Thank you sigod, that is exactly what I've done. I calculate the time until next 8:00 AM and call setTimer. Here is the code for further reference:
void startDailyTaskAtTime(TimeOfDay time, void delegate() task) {
// Get the current date and time
DateTime now = cast(DateTime)Clock.currTime();
// Get the next time occurrence
DateTime nextOcc = cast(DateTime)now;
if (now.timeOfDay >= time) {
nextOcc += dur!"days"(1);
}
nextOcc.timeOfDay = time;
// Get the duration before now and the next occurrence
Duration timeBeforeNextOcc = nextOcc - now;
void setDailyTask() {
// Run the task once
task();
// Run the task all subsequent days at the same time
setTimer(1.days, task, true);
}
setTimer(timeBeforeNextOcc, &setDailyTask);
}

Related

How to set a timer in solidity?

I am launching a game that should close after exactly 3 days/72 hours of initializing & deploying the contract.
My current thoughts are:
declare a variable, timestamp.
in the constructor, set the variable timestamp to block.timestamp
add 3 days worth of time [in milliseconds i presume] to the timestamp variable
do a require(block.timestamp < timestamp) in the game logic [users call a write function, so I can do it in there], so users cannot write the function if block.timestamp is past timestamp + 3 days
Is this is a feasible solution? Is there a better solution? Is there a more gas efficient solution?
Thanks in advance
I just wrote this:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;
contract MyContract{
uint start;
uint end;
modifier timeIsOver{
require(block.timestamp<=end,"Time is up");
_;
}
// Firstly, call this
function startTimer() public{
start=block.timestamp;
}
// Secondly, call this
// timestamp of the current block in seconds since the epoch
// period is in seconds
function endTimer(uint period) public {
end=period+start;
}
function timeLeft() public view returns(uint){
return end-block.timestamp;
}
function callThisWhenTimeIsUp() external timeIsOver{
// write the logic here
}
}
Or you could use oracle to set up timer. Oracle is external serice that you use in ethereum. an example: https://blog.chain.link/blockchain-voting-using-a-chainlink-alarm-clock-oracle/

Make an event end between 2 hours and excluding week-end

I'm working on a planning application on QML. I'm trying to write the function which allows to calculate startTime and endTime of an event. My event must start between at a startDayTime and an endDayTime for example 9 a.m. and 3 p.m. The event should not end on week-end too. The endTime must respect these conditions too.
I'm trying to calculate the start time in order to have both start and end time to respect hour boundaries.
This is my program:
QDateTime Planning::enDateCalculProcess(QDateTime &startTime, qint64 &time,qint64 &workTime,qint64 &iraTime,QTime &startDayTime, QTime &endDayTime)
{
qint64 remainingTimeInStartDate= startTime.time().secsTo(endDayTime);
if(time <= remainingTimeInStartDate){
startTime=startTime.addSecs(time);
return startTime.addSecs(iraTime);
}
else{
qint64 numOfDays= time/workTime;
qint64 remainingTime= time % workTime;
qDebug()<<numOfDays<<"//"<<remainingTime;
startTime=startTime.addDays(numOfDays);
if(remainingTime > startTime.time().secsTo(endDayTime)){
startTime=startTime.addDays(1);
startTime.setTime(startDayTime);
startTime=startTime.addSecs(remainingTime);
if(!isWeekDay(startTime)){
QDateTime nexStart=startTime.addDays(8 -startTime.date().dayOfWeek());
nexStart.setTime(startDayTime);
startTime=nexStart.addSecs(remainingTime);
}
}
else{
startTime=startTime.addSecs(remainingTime);
if(!isWeekDay(startTime)){
QDateTime nexStart=startTime.addDays(8 -startTime.date().dayOfWeek());
nexStart.setTime(startDayTime);
startTime=startTime.addSecs(remainingTime);
}
}
startTime=startTime.addSecs(remainingTime);
QDateTime endDate=startTime.addSecs(iraTime);
return endDate;
}
}
I have initially calculated the start and endTime and in case it does not match the conditions I call this function. The user select the start time and we calculate the end by adding the irradiation time to it (iraTime). We must propose a start and end to the user to respect the boundaries.

Delaying actions using Decentraland's ECS

How do I make an action occur with a delay, but after a timeout?
The setTimeout() function doesn’t work in Decentraland scenes, so is there an alternative?
For example, I want an entity to wait 300 milliseconds after it’s clicked before I remove it from the engine.
To implement this you’ll have to create:
A custom component to keep track of time
A component group to keep track of all the entities with a delay in the scene
A system that updates the timers con all these
components on each frame.
It sounds rather complicated, but once you created one delay, implementing another delay only takes one line.
The component:
#Component("timerDelay")
export class Delay implements ITimerComponent{
elapsedTime: number;
targetTime: number;
onTargetTimeReached: (ownerEntity: IEntity) => void;
private onTimeReachedCallback?: ()=> void
/**
* #param millisecs amount of time in milliseconds
* #param onTimeReachedCallback callback for when time is reached
*/
constructor(millisecs: number, onTimeReachedCallback?: ()=> void){
this.elapsedTime = 0
this.targetTime = millisecs / 1000
this.onTimeReachedCallback = onTimeReachedCallback
this.onTargetTimeReached = (entity)=>{
if (this.onTimeReachedCallback) this.onTimeReachedCallback()
entity.removeComponent(this)
}
}
}
The component group:
export const delayedEntities = engine.getComponentGroup(Delay)
The system:
// define system
class TimerSystem implements ISystem {
update(dt: number){
for (let entity of delayedEntities.entities) {
let timerComponent = entity.getComponent(component)
timerComponent.elapsedTime += dt
if (timerComponent.elapsedTime >= timerComponent.targetTime){
timerComponent.onTargetTimeReached(entity)
}
})
}
}
// instance system
engine.addSystem(new TimerSystem())
Once all these parts are in place, you can simply do the following to delay an execution in your scene:
const myEntity = new Entity()
myEntity.addComponent(new Delay(1000, () => {
log("time ran out")
}))
engine.addEntity(myEntity)
A few years late, but the OP's selected answer is kind of deprecated because you can accomplish a delay doing:
import { Delay } from "node_modules/decentraland-ecs-utils/timer/component/delay"
const ent = new Entity
ent.addComponent(new Delay(3 * 1000, () => {
// this code will run when time is up
}))
Read the docs.
Use the utils.Delay() function in the utils library.
This function just takes the delay time in milliseconds, and the function you want to execute.
Here's the full documentation, explaining how to add the library + how to use this function, including example code:
https://www.npmjs.com/package/decentraland-ecs-utils

How do I know a task's start time of Task Scheduler through Windows API?

I want to know this start time in code.
I found this Mircosoft document about ITask.
It provides some methods to get the task's information such as application name, max run time and working directory ... but doesn't have what I need - start time.
The task start time is associated with the task trigger, not the task itself.
In the following code you need to initialize IRegisteredTask with the task that you are looking for.
Notice that a task may have more than one trigger and each could have a different type.
void GetStartTime(IRegisteredTask* pTask)
{
ITaskTrigger *pTT = NULL;
TASK_TRIGGER Trigger;
ITaskDefinition *pDefinition = NULL;
ITriggerCollection *pTriggers = NULL;
pTask->get_Definition(&pDefinition);
pDefinition->get_Triggers(&pTriggers);
LONG cTriggers = 0;
pTriggers->get_Count(&cTriggers);
while (cTriggers > 0)
{
ITrigger *pT = NULL;
pTriggers->get_Item(cTriggers, &pT);
cTriggers--;
BSTR bStart;
pT->get_StartBoundary(&bStart);
/*
bStart will be some thing like L"2013-08-01T12:05:00"
*/
::SysFreeString(bStart);
pT->Release();
}
pTriggers->Release();
}

ColdFusion - Get next scheduled task due to run

This thread was useful in finding out the next run-time for a scheduled task.
How do I find out the next run time for a Scheduled Task?
But, is there also a way to simply get the next scheduled task due to run?
If I can get the date and name of the next task due to run, I can plug that date into a jQuery countdown timer, which will display a countdown to the next scheduled task, something like:
TaskABC due to run in:
12 03 20
hrs min sec
. This is for an admin interface in case you're wondering how geeky can people get:-)
EDIT
I had the same thought as Bill. But was curious if there was another way.
I poked around and apparently the internal Scheduler class maintains a list of upcoming tasks. The list is private, but you can use the same reflection technique to access it. Interestingly the list also includes system tasks like the mail spooler, session/application trackers, watchers, etecetera. So you must iterate through it until you find a "scheduled task" ie CronTabEntry
Below is a very lightly tested function that seems to do the trick in CF9. (Note, includes the CreateTimeStruct function from http://www.cflib.org).
Rules:
Returns a structure containing the name and time remaining until the next task. If no tasks were found, result.task is an empty string.
Excludes paused tasks
Usage:
result = new TaskUtil().getNextTask();
WriteDump(result);
CFC
component {
public struct function getNextTask() {
// get list of upcoming tasks from factory (UNDOCUMENTED)
local.scheduler = createObject("java", "coldfusion.server.ServiceFactory").getSchedulerService();
local.taskField = local.scheduler.getClass().getDeclaredField("_tasks");
local.taskField.setAccessible( true );
local.taskList = local.taskField.get(local.scheduler);
// taskList contains system jobs too, so we must iterate
// through the tasks to find the next "scheduled task"
local.nextTask = "";
local.tasks = local.taskList.iterator();
while ( local.tasks.hasNext() ) {
local.currTask = local.tasks.next();
local.className = local.currTask.getRunnable().getClass().name;
// exit as soon as we find a scheduled task that is NOT paused
if (local.className eq "coldfusion.scheduling.CronTabEntry"
&& !local.currTask.getRunnable().paused) {
local.nextTask = local.currTask;
break;
}
}
// if we found a task, calculate how many days, hours, etcetera
// until its next run time
local.details = { task="", remaining={} };
if ( isObject(local.nextTask) ) {
local.secondsToGo = (local.nextTask.getWhen() - now().getTime()) / 1000;
local.details.task = local.nextTask.getRunnable().task;
local.details.remaining = createTimeStruct(local.secondsToGo);
local.details.nextDate = dateAdd("s", local.nextTask.getWhen() / 1000
, "January 1 1970 00:00:00" );
}
return local.details;
}
/**
* Abbreviated version of CreateTimeStruct by Dave Pomerance
* See http://www.cflib.org/index.cfm?event=page.udfbyid&udfid=421
*
* #param timespan The timespan to convert.
* #return Returns a structure.
* #author Dave Pomerance
* #version 1, January 7, 2002
*/
public struct function CreateTimeStruct(required numeric timespan) {
var timestruct = StructNew();
var mask = "s";
// only 4 allowed values for mask - if not one of those, return blank struct
if (ListFind("d,h,m,s", mask)) {
// compute seconds
if (mask eq "s") {
timestruct.s = (timespan mod 60) + (timespan - Int(timespan));
timespan = int(timespan/60);
mask = "m";
} else timestruct.s = 0;
// compute minutes
if (mask eq "m") {
timestruct.m = timespan mod 60;
timespan = int(timespan/60);
mask = "h";
} else timestruct.m = 0;
// compute hours, days
if (mask eq "h") {
timestruct.h = timespan mod 24;
timestruct.d = int(timespan/24);
} else {
timestruct.h = 0;
timestruct.d = timespan;
}
}
return timestruct;
}
}
My first thought is to iterate Leigh's getNextRunTime(string taskName) function over the collection of tasks. You can get an array of structs containing the details of all scheduled tasks using taskArray = createobject("java","coldfusion.server.ServiceFactory").getCronService().listAll();
The key in the struct containing the task name is "task". So you can extract all the task names as an array for example, run Leigh's function on each element and determine which one will run next.