How to perform a task at a precise time in time?

24
  

A style question Code Golf

I've done a console program to show the hours, only hours different from what we know - and involves a It's very simple.

It checks the system time, and finds that a minute has passed, it prints the current time calculated on the screen.

Examples of its output:

35.5787037037037
35.69444444444444
36.388888888888886

However, I would like it to work a little better:

  

I would like it to have the accuracy of a second, or a .beat

To do this, I should be able to create a task linked to the system clock, so that it warned me precisely when I determined it.

I know it's possible to do an infinite loop , and check the system time thousands of times - but I do not really like the idea. The ideal would be to have a listener that would inform me that it is time to perform my task.

Is this possible? How to make? (Is there any magic, voodoo that will allow this?)

  
  • I would like simple examples, in different languages
  •   
  • Console program
  •   
  • No need to implement the .beat account
  •   
  • The idea is to free the program to do other things and have the task started at a precise moment in time
  •   
  • One language per response!
  •   

The account, for those who are curious, is this:
(UTC+1segundos + (UTC+1minutos * 60) + (UTC+1horas * 3600)) / 86.4     
asked by anonymous 11.06.2017 / 02:21

5 answers

19

Python

In Python there is the sched package that can be used to schedule tasks at certain points in the time. See the example:

import sched, time, threading, sys

trigger = time.mktime((2017, 6, 14, 21, 15, 36, 0, 0, 0))

def task(trigger):
    sys.stdout.write("Tarefa executada com um erro de " + str(time.time() - trigger) + ' segundos\n')

s = sched.scheduler(time.time, time.sleep)

s.enterabs(trigger, 1, task, argument=(trigger,))

t = threading.Thread(target=s.run)
t.start()

while t.is_alive(): pass # Simula o programa executando normalmente

For the example above, the task function will run exactly on 2017-06-14 at 21:15:36, displaying the message (for example):

Tarefa executada com um erro de 0.0057599544525146484 segundos
  

See working at Repl.it

Reference of functions used:

sched.scheduler sched.scheduler.enterabs sched.scheduler.run time.mktime time.time time.sleep threading.Thread threading.Thread.start threading.Thread.is_alive

    
15.06.2017 / 01:16
9

In Java:

import java.time.ZonedDateTime;
import java.time.ZoneOffset;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Swatch {
    public static void main(String[] args) {
        // Recebe a entrada em .beats e converte para milisegundos desde a meia-noite.
        int milisegundosAgendamento = Integer.parseInt(args[0]) * 86400;

        // Hora atual no fuso horário UTC+1.
        ZonedDateTime utc1 = ZonedDateTime.now(ZoneOffset.ofHours(1));

        // Calcula a quantidade de milisegundos desde a meia-noite que se passaram neste momento.
        int milisegundosAgora = utc1.getHour() * 3600000 + utc1.getMinute() * 60000 + utc1.getSecond() * 1000 + utc1.getNano() / 1000000;

        // Calcula quantos milisegundos faltam para chegar a hora certa. O if serve para o caso de a hora certa ser amanhã, e não hoje.
        int milisegundosQueFaltam = milisegundosAgendamento - milisegundosAgora;
        if (milisegundosQueFaltam < 0) milisegundosQueFaltam += 86400000;

        // Cria um objeto responsável por executar tarefas em momentos pré-agendados.
        ScheduledThreadPoolExecutor agendador = new ScheduledThreadPoolExecutor(1);

        // Agenda a tarefa de mostrar a hora e fechar o agendamento:
        agendador.schedule(() -> {
            System.out.println("Chegou a hora");
            agendador.shutdown();
        }, milisegundosQueFaltam, TimeUnit.MILLISECONDS);
    }
}

The above code shows the message Chegou a hora when the time is right. There is no error checking on the input, it assumes that it will receive an integer from 0 to 999. After the time has expired, the program ends.

However, considering the original rules of code-golf aimed at minimizing the size of the code- source, I come to this other version down here with 404 373 366 bytes . In it, the message that the time has come is just the program returning status 5 to the operating system when the time comes. Its accuracy is tenths of a second rather than milliseconds just like the code above. Again, there is no verification about whether or not the entry is valid:

import java.time.*;import java.util.concurrent.*;class S{public static void main(String[]x){ZonedDateTime z=ZonedDateTime.now(ZoneOffset.ofHours(1));int g=Integer.parseInt(x[0])*864-z.getHour()*36000-z.getMinute()*600-z.getSecond()*10-z.getNano()/100000000;new ScheduledThreadPoolExecutor(1).schedule(()->System.exit(5),(g<0?g+864000:g)*100,TimeUnit.MILLISECONDS);}}
    
25.06.2017 / 18:55
4

In C #

the same can be done using a timer .

The most complicated part is to handle the case of when the timer should start. Since there is no simple API to do this you have to resort to other mechanisms like Thread.Sleep .

System.Timers.Timer StartTimer(TimeSpan interval, Action onTick, DateTime? startAt = null){
    startAt = startAt ?? DateTime.UtcNow;
    var timer =  new  System.Timers.Timer();
    timer.Interval = interval.TotalMilliseconds;
    timer.Elapsed += (ctx, arg) => onTick();
    timer.AutoReset = true;

    //evita o bloqueamento da thread chamadora.
    ThreadPool.QueueUserWorkItem(ctx =>{  
        //espera até que o momento atual seja aproximadamente 'startAt'
        Thread.Sleep(Math.Max(0, (DateTime.UtcNow - startAt).TotalMilliseconds));
        //chama o callback e comeca o timer que vai chamar o callback em intervalos
        onTick();
        timer.Start();
    });
    return timer;
}

StartTimer(TimeSpan.FromMinutes(1), () => Console.WriteLine("Tick"));
    
25.06.2017 / 14:41
1

In Javascript

Can be done using setTimeout and some recursion.

function setIntervalDelayed(delay, interval, cb){
    setTimeout(function(){
        cb();
        setIntervalDelayed(interval, interval, cb);
    }, delay);
}

setIntervalDelayed(1000, 5000, function(){console.log('Tick');});
    
25.06.2017 / 16:08
1

In C:

#include <stdio.h>
#include <time.h>
#include <unistd.h>


void callback_func( time_t t )
{
    printf("CallBack: %ld\n", t );
}


void timer( int intervalo, void (*func)(time_t) )
{
    time_t atual;
    time_t ultima;

    while(1)
    {
        atual = time(NULL);

        if( atual >= ultima + intervalo )
        {
            func( atual );
            ultima = atual;
        }

        usleep( (intervalo / 10) * 1000000L );
    }

}

int main( int argc, char * argv[] )
{
    timer( 1, callback_func );
    return 0;
}

Output:

CallBack: 1498509557
CallBack: 1498509558
CallBack: 1498509559
CallBack: 1498509560
CallBack: 1498509561
CallBack: 1498509562
CallBack: 1498509563
CallBack: 1498509564
CallBack: 1498509565
CallBack: 1498509566
CallBack: 1498509567
CallBack: 1498509568
CallBack: 1498509569
CallBack: 1498509570
    
26.06.2017 / 22:40