单击两次按钮的持续时间 returns 错误值

Duration for two button clicks returns false values

我正在尝试计算用户休息时间,方法是在用户休息之前单击,然后在他完成休息后单击另一个按钮。我偶然发现了几个问题,读到最好的方法是使用 nanoTime() 方法。

System.nanoTime();

但问题是当我计算持续时间时它 returns 奇怪的值。

这是我的代码,

        btnStartBreak.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                breakStartTime = System.nanoTime();
                breakTv.setText("Do you want to finish the break?");
                btnStartBreak.setVisibility(View.GONE);
                btnFinishBreak.setVisibility(View.VISIBLE);
            }
        });

        btnFinishBreak.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                breakFinishTime = System.nanoTime();
                long breakTime = breakFinishTime - breakStartTime;
                Toast.makeText(getApplicationContext(), getDate(TimeUnit.NANOSECONDS.toMillis(breakTime), "mm:ss:SSS"), Toast.LENGTH_LONG).show();
            }
        });

        public static String getDate(long milliSeconds, String dateFormat){
        // Create a DateFormatter object for displaying date in specified format.
        SimpleDateFormat formatter = new SimpleDateFormat(dateFormat);

        // Create a calendar object that will convert the date and time value in milliseconds to date.
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(milliSeconds);
        return formatter.format(calendar.getTime());
        }

我已经用这个 link 将毫秒转换为小时和分钟。

我将在此处提供我的评论作为答案以及其他信息。

您正在使用 System.nanotime(),根据 docs

Returns the current value of the most precise available system timer, in nanoseconds.

但是您的方法getDate()需要以毫秒为单位的时间。所以你提供的价值是大了 1,000,000 倍。

相反,您可以使用 System.currentTimeMillis(),这将为您提供所需的时间(以毫秒为单位)。

编辑:

看来你想计算一个时间跨度,并以minutes:seconds:millis的形式显示出来。不要为此使用 Calendar and/or Date。而且你不需要 SimpleDateFormat.

你已经知道两个动作的时间差了。有一种更简单的方法来格式化该时间跨度。您可以使用以下代码段进行转换:

public static String formatMillis(long ms) {
    long rest = ms;
    long minutes = rest / (1000 * 60);

    rest = rest % (1000 * 60);
    long seconds = rest / 1000;
    long millis = rest % 1000;

    return String.format("%02d:%02d:%03d", minutes, seconds, millis);
}

输入:

formatMillis(5000L);
formatMillis(60000L);
formatMillis(67890L);

输出:

00:05:000
01:00:000
01:07:890

我对您的代码做了一些实验,同时使用了 System.nanoTime()System.currentTimeMillis(),并且在这两种情况下我都成功了。

使用System.currentTimeMillis()

long breakStartTime, breakTime;
 btnStartBreak.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                breakStartTime = System.currentTimeMillis();
                breakTv.setText("Do you want to finish the break?");
                btnStartBreak.setVisibility(View.GONE);
                btnFinishBreak.setVisibility(View.VISIBLE);
            }
        });

    btnFinishBreak.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            breakTime = System.currentTimeMillis() - breakStartTime ;
            Toast.makeText(getApplicationContext(), getDate(breakTime, "mm:ss.SSS"), Toast.LENGTH_LONG).show();
        }
    });

使用System.nanoTime()
nanoTime() 专门用于测量经过的时间,而 currentTimeMillis() 依赖于系统时钟设置的时间,可以更改。所以最好使用 nanoTime() 来计算经过的时间。

long breakStartTime, breakTime , durationInMs;
btnStartBreak.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    breakStartTime = System.nanoTime();
                    breakTv.setText("Do you want to finish the break?");
                    btnStartBreak.setVisibility(View.GONE);
                    btnFinishBreak.setVisibility(View.VISIBLE);
                }
            });

    btnFinishBreak.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            breakTime = System.nanoTime() - breakStartTime ;
            //convert nanoseconds value to milliseconds
            durationInMs = TimeUnit.MILLISECONDS.convert(breakTime , TimeUnit.NANOSECONDS); 
            Toast.makeText(getApplicationContext(), getDate(durationInMs, "mm:ss.SSS"), Toast.LENGTH_LONG).show();
        }
    });