【问题标题】:Duration for two button clicks returns false values两次按钮单击的持续时间返回错误值
【发布时间】:2016-03-19 05:35:19
【问题描述】:

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

System.nanoTime();

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

这是我的代码,

        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 将毫秒转换为小时和分钟。

【问题讨论】:

  • 所以你打电话给getDate,它需要毫秒的时间,但你提供的时间是纳秒?你差了 1,000,000 倍。
  • 哦,原来如此。
  • 好吧,我使用了 TimeUnit.NANOSECONDS.toMillis(breakTime) 但现在它仅显示 31:45:284 值持续两分钟。

标签: java android date buttonclick milliseconds


【解决方案1】:

我对你的代码做了一个小实验,同时使用了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();
        }
    });

【讨论】:

  • 这应该是公认的答案,+1 用于比较 nanoTime() 和 currentTimeMillis() 以及推荐 nanoTime()。
【解决方案2】:

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

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

返回最精确的可用系统计时器的当前值,以纳秒为单位。

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

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

编辑:

您似乎想计算一个时间跨度并以minutes:seconds:millis 的形式显示它。不要为此使用Calendar 和/或Date。而且你不需要SimpleDateFormat

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

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

【讨论】:

  • 在我使用 nanoTime() 之前,我使用了 currentTimeMillis() 方法。但它没有正常工作。这就是我选择使用这种方法的原因。
  • 是的,我尝试了 formatMillis() 方法,它的输出是正确的。非常感谢!
  • currentTimeMillis() 取决于系统时钟,因此不推荐使用。
猜你喜欢
  • 2010-12-31
  • 2022-10-23
  • 1970-01-01
  • 1970-01-01
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多