在 Ada 中,如何将当前时间(以秒为单位)作为可以打印出来并执行操作的值?

Posted

技术标签:

【中文标题】在 Ada 中,如何将当前时间(以秒为单位)作为可以打印出来并执行操作的值?【英文标题】:In Ada, how do I get the current time in seconds as a value I can print out and perform operations with? 【发布时间】:2013-12-05 20:10:49 【问题描述】:

我正在为一个操作系统类做一个项目。我需要编写一个程序,每十秒打印一次当前时间,但还要考虑开销的延迟,以便它在长时间运行时不会漂移。我还需要它至少保持小数点后 1 位。

我被困在第 1 步,因为我不知道如何以秒为单位获取当前时间作为值。我已经搜索但只能找到如何以 HH:MM:SS 格式获取当前时间。

谢谢

【问题讨论】:

您应该在此处发布您的代码。检查指南 How to Ask 和 SSCCE 你看过Ada.Calendar和Ada.Real_Time的定义了吗?你能解释一下为什么那个包中的操作不能满足你的需要吗? 我知道我可能遗漏了一些明显的东西,但我看不到从这些定义中获取值的方法。 “价值”是什么意思?如果您尝试将“当前时间(以秒为单位)”作为单个数字返回,您需要意识到没有这样的事情,除非它与某个其他时间点有关,即“自某个特定时间以来的秒数时间点(例如 1970 年 1 月 1 日午夜)。如果这是您需要的,可以从 Ada.Calendar 轻松获得。 【参考方案1】:

这是我想出的:

writing_test.ads

package Writing_Test is

    protected Writer is
        entry write( Text : String; New_Line : Boolean:= True );
    end Writer;

    task Timer is
        entry Start;
        entry Pause;
        entry Stop;
    end Timer;


private

    Timer_Frequency : constant Duration:= 10.0;

end Writing_Test;

writing_test.adb

with
Ada.Calendar,
Ada.Text_IO;

package body Writing_Test is

    protected body Writer is
        entry write( Text : String; New_Line : Boolean:= True ) when True is
        begin
            Ada.Text_IO.Put( Text );

            if New_Line then
                Ada.Text_IO.New_Line;
            end if;
        end;
    end Writer;

    task body Timer is
        Active,
        Stop_Task : Boolean:= False;

        Next_Time : Ada.Calendar.Time;
        use type Ada.Calendar.Time;
    begin
        MAIN:
        loop
            if not Active then
                select
                    accept Start do
                        Active:= True;
                        Next_Time:= Ada.Calendar.Clock + Timer_Frequency;
                    end Start;
                or
                    terminate;
                end select;
            else
                select
                    accept Pause do
                        Active:= False;
                    end Pause;
                or
                    accept Stop do
                        Stop_Task:= True;
                    end Stop;
                or
                    delay until Next_Time;
                end select;

                exit MAIN when Stop_Task;

                if Active then
                    declare
                        Use Ada.Calendar;
                        Now : Time renames Clock;
                        Str : String renames
                          Day_Duration'Image( Ada.Calendar.Seconds(Now) );
    --' Formatter-correction trick
                    begin
                        Writer.write(Text => Str);
                        Next_Time:= Next_Time + Timer_Frequency;
                    end;
                end if;
            end if;        
        end loop MAIN;

    end Timer;

end Writing_Test;

【讨论】:

您已经回答了整个班级的问题(而不仅仅是 OP 实际提出的问题)。另外,在受保护的操作中调用Text_IO 不是有界错误吗? 是的,这是一个有界错误;我也不确定我的回答是否正确:对于某些定义,这可能会“漂移”——因为它在操作完成后重置为 10 秒,而不是始终在 Start+(n*10)n in Integer 处执行。 是的,这两句话都是真的。受保护操作中潜在的阻塞调用是一个错误(参见 rm 9.5.1 受保护的子程序和受保护的操作)。另外,这个程序有偏差,您应该对其进行编辑,以便始终从开始时间计算 Next_Time。 我怀疑这个程序会漂移。 1:计时部分直接按书。 2:Ada中时间相关的类型都是定精度类型。 (但我当然愿意解释为什么它会漂移。) @Jacob,我改了:Writer.Write 之后的赋值是:Next_Time:= Now + Timer_Frequency;【参考方案2】:

这是一个执行“每 10 秒打印一次”部分的简单程序。您可以轻松地在单独的包中使用此代码。

with Ada.Text_IO;
with Ada.Calendar;

procedure Periodic_Printer is

   task type My_Printer_Task is
   end My_Printer_Task;

   task body My_Printer_Task is
      use Ada.Calendar; -- for the "-" and "+" operations on Time
      Start_Time : Ada.Calendar.Time;
      Next_Cycle : Ada.Calendar.Time;
      Period     : constant Duration  := 10.0;
   begin
      Start_Time := Ada.Calendar.Clock;
      Next_Cycle := Start_Time;
      loop
         Ada.Text_IO.Put_Line(Duration'Image(Ada.Calendar.Clock - Start_Time)); --'
         -- You could use Next_Cycle instead of Ada.Calendar.Clock - Start_Time
         -- so the printing does not depend of the time needed to do the elapsed
         -- time calculation

         delay 3.0; -- like a long operation, takes time......
                    -- This pattern assumes the each cycle last less than Period
                    -- If you cannot ensure that, you should consider improving
                    -- the pattern or reduce the computation load of each cycle

         Next_Cycle := Next_Cycle + Period;
         delay until Next_Cycle;
      end loop;
   end My_Printer_Task;

   Printer : My_Printer_Task;
begin
   delay 90.0; -- You can do your 'real work' here.

   -- Unclean way to terminate a task, you should consider improve it for a
   -- real world scenario
   abort Printer;

   Ada.Text_IO.Put_Line("End of program");
end Periodic_Printer;

【讨论】:

以上是关于在 Ada 中,如何将当前时间(以秒为单位)作为可以打印出来并执行操作的值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift3 中以秒为单位将字符串更改为分钟?

返回要使用 AudioTrack 播放的曲目的长度(以秒为单位)

如何测量 powershell 脚本中不同功能的持续时间(以秒为单位)?

如何检查两个日期之间的差异(以秒为单位)?

获取 Go 语言中的 Unix 时间戳(当前时间,以秒为单位)

获取自 Linux 上的 Epoch、Bash 以来的当前时间(以秒为单位)