Hướng dẫn sử dụng java Clock

Trong bài viết này chúng ta sẽ cùng nhau tìm hiểu về Clock class thuộc package java.time trong java. Để dễ hiểu thì các bạn cứ xem clock là một cái đồng hồ, với các múi giờ khác nhau thì những cái đồng hồ này sẽ có giá trị khác nhau. 

Clock class là một abstract class vì vậy chúng ta không thể khởi tạo nó, tuy nhiên chúng ta có thể sử dụng một số static method được định nghĩa trong nó.

Hầu hết các Date API đều cung cấp các method để thao tác với ngày giờ, nên việc sử dụng Clock là optional. Sử dụng Clock khi bạn muốn thay đổi đồng hồ mặc định trong hệ thống.

Clock class thường được sử dụng trong các mục đích kiểm thử tốc độ của một đoạn chương trình. Từ đó chúng ta có thể biết được chính xác ở đâu trong chương trình có tốc độ thực thi chậm và có kế hoặc để tối ưu hoá chúng.

Clock cũng có thể thay thế System.currentTimeMillis()TimeZone.getDefault();

Các method trong Clock

Như đã đề cập ở trên thì Clock là một abstract method vậy nên dưới đây là các static method của Clock class và các instance method của các child class của Clock. Chúng ta sẽ cùng nhau tìm hiểu xem các sử dụng của chúng nha.

systemDefaultZone()

systemDefaultZone() trả về một instance của Clock sử dụng múi giờ mặc định của hệ thống.

// Syntax 
public static Clock systemDefaultZone()

// Example 

Clock clock = Clock.systemDefaultZone();

System.out.println(clock.getZone()); // Asia/Ho_Chi_Minh 

System.out.println(clock.millis()); // 1577679681906

Note:

  • Kết quả có thể khác nhau khi chạy trên các máy khác nhau tuỳ thuộc vào múi giờ mà máy các bạn đang sử dụng.
  • Bên trong systemDefaultZone() khởi tạo một instance của ClockSystem class thừa kế từ Clock.

instant()

Trả về instant – thời gian hiện tại của clock.

// Syntax
public abstract Instant instant();

// Example

Clock clock = Clock.systemDefaultZone();

Instant instant = clock.instant();

System.out.println(instant); // 2019-12-30T05:26:44.897Z

systemUTC()

systemUTC() trả về một instance của Clock, khi bạn cần sử dụng đến Instant mà không cần ngày hay thời gian thì nên sử dụng nó thay thế cho systemDefaultZone().

// Syntax
public static Clock systemUTC()

// Example

Clock clock = Clock.systemUTC();

System.out.println(clock.getZone()); // "Z"

system(ZoneId zone)

system() Trả về một instance clock với múi giờ được chỉ định.

// Syntax
public static Clock system(ZoneId zone)

// Example

Clock clock = Clock.system(ZoneId.of("Europe/Paris"));

System.out.println(LocalDateTime.now(clock)); //
2019-12-30T07:06:16.552

millis()

millis() trả về số miliseconds của instance clock.

// Syntax
public long millis()

// Example 
Clock clock = Clock.systemDefaultZone();

System.out.println(clock.millis()); // 1577686459704

millis() tương đương với System.currentTimeMills().

Clock clock = Clock.systemDefaultZone();
System.out.println(clock.millis()); // 1577686602462

System.out.println(System.currentTimeMillis()); //1577686602462

Note:  Số miliseconds là hằng số và luôn giống nhau ở bất kỳ múi giờ nào.

Clock clock = Clock.system(ZoneId.of("Europe/Paris"));
System.out.println(clock.millis()); // 1577686785161

System.out.println(System.currentTimeMillis()); // 1577686785161

offset(Clock baseClock, Duration offsetDuration)

offet() method trả về một instance của Clock với Instant bằng tổng của Instant của baseClock với một khoảng thời gian offsetDuration từ tham số truyền vào.

Nếu offsetDuration âm chúng ta sẽ một clock quay trở về thời gian trong quá khứ, nếu offsetDuration chúng ta sẽ có clock thời gian trong tương lai. offset() thường được sử dụng để tính thời gian trong tương lai hoặc quá khứ. 

// Syntax
public static Clock offset(Clock baseClock, Duration offsetDuration)


// Example 
Clock baseClock = Clock.systemDefaultZone();

Clock pastClock = Clock.offset(baseClock, Duration.ofMillis(-10000));
System.out.println(baseClock.millis() - pastClock.millis()); //prints 10000

Clock futureClock = Clock.offset(baseClock, Duration.ofDays(1));
System.out.println(futureClock.millis() - baseClock.millis()); //prints 86400000

tick(Clock baseClock, Duration tickDuration)

tick() trả về một instance Clock từ baseClock instant cắt ngắn gần đến lần xuất hiện gần nhất của baseClock với khoảng tickDuration.

// Syntax
public static Clock tick(Clock baseClock, Duration tickDuration)

// Example
import java.time.*;

class Main {

    public static void main(String[] args) {

        Clock baseClock = Clock.systemDefaultZone();
        Clock tickClock = Clock.tick(baseClock, Duration.ofMillis((100)));
        for (int i = 1; i <= 3; i++) {
            System.out.println("-----" + i + "-----");
            System.out.println("Base: " + baseClock.instant());
            System.out.println("Tick: " + tickClock.instant());
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

Output:


—–1—–
Base: 2019-12-30T12:12:57.835Z
Tick: 2019-12-30T12:12:57.800Z
—–2—–
Base: 2019-12-30T12:13:00.850Z
Tick: 2019-12-30T12:13:00.800Z
—–3—–
Base: 2019-12-30T12:13:03.852Z
Tick: 2019-12-30T12:13:03.800Z

Các bạn thấy thời gian được làm tròn đến 100milis.

Note:

  • Nếu tickDuration của chúng ta là 1milis thì chúng ta có thể dùng tickMillis() và 1 phút thì sử dụng tickMinutes().
  • tickDuration phải là giá trị dương.

fixed(Instant fixedInstant, ZonedId zone)

fixed() trả về một instance của Clock và instance này luôn trả về Instant có cùng giá trị.

// Syntax 
public static Clock fixed(Instant fixedInstant, ZoneId zone)

// Example
import java.time.*;

class Main {

    public static void main(String[] args) throws InterruptedException {
        Clock fixedClock = Clock.fixed(Instant.now(), ZoneId.systemDefault());
        System.out.println(fixedClock); // FixedClock[2019-12-30T09:34:15.343Z,Asia/Ho_Chi_Minh]
        System.out.println(fixedClock.instant()); // 2019-12-30T09:34:15.343Z
        Thread.sleep(1000);
        System.out.println(fixedClock.instant()); // 2019-12-30T09:34:15.343Z

    }
}

Một số cách áp dụng Clock 

Đo thời gian thực thi

Khi ứng dụng của bạn chạy quá trình và bạn muốn nó chạy nhanh hơn. Sau khi chúng ta chạy chương trình và xác định những đoạn code có liên qua thì việc tiếp theo là chúng ta phải đo xem những đoạn code đó thực thi trong bao lâu và sau khi tối ưu thì nó sẽ chạy trong bao lâu để đánh giá độ hiểu quả.

Ví dụ tính tổng các số nguyên từ 0 đến 1000000000

import java.time.*;

class Main {

    public static void main(String[] args) {

        long before = Clock.systemDefaultZone().millis();
        long sum = 0;
        for(int i = 0; i < 1000000000; i++)
            sum+=i;

        System.out.println("Sum: " + sum);
        long after = Clock.systemDefaultZone().millis();

        System.out.println("Thoi gian thu thi: " + (after - before));
    }
}

Output: 

Sum: 499999999500000000
Thoi gian thu thi: 346

Đồng hồ đa quốc gia

Nếu bạn đã từng thấy các đồng hồ điện tử hiện đại ngày nay thì ngoài hiển thị giờ của Việt Nam thì nó còn có giờ của những thành phố khác trên thế giới như là Paris, Los Angeles etc. Hôm nay chúng ta sẽ làm thử đồng hiển thị giờ của 4 thành phố lớn: HCM, Paris, Los Angeles,  Darwin nhưng với giao diện console, nếu các bạn muốn phát triển thêm thì có thể sử dụng thêm một số package hỗ trợ làm UI của java nhé. 

Trong ví dụ dưới đây ngoài sử dụng Clock class thì mình còn sử dụng thêm LocalDateTime để hỗ trợ chuyển sang ngày giờ cho các bạn dễ nhìn.

import java.time.*;

class Main {

    public static void main(String[] args) throws InterruptedException {


        Clock sys = Clock.systemDefaultZone();

        Clock clockPr = Clock.system(ZoneId.of("Europe/Paris"));


        Clock clockArLos = Clock.system(ZoneId.of("America/Los_Angeles"));


        Clock clockAuDar = Clock.system(ZoneId.of("Australia/Darwin"));

        while (true) {

            Thread.sleep(1000);

            LocalDateTime dateTimeSys = LocalDateTime.now(sys);

            System.out.println("System: " + dateTimeSys.getHour() + ":" + dateTimeSys.getMinute() + ":" + dateTimeSys.getSecond());

            LocalDateTime dateTimePr = LocalDateTime.now(clockPr);

            System.out.println("Paris: " + dateTimePr.getHour() + ":" + dateTimePr.getMinute() + ":" + dateTimePr.getSecond());

            LocalDateTime dateTimeLos = LocalDateTime.now(clockArLos);

            System.out.println("Los Angeles: " + dateTimeLos.getHour() + ":" + dateTimeLos.getMinute() + ":" + dateTimeLos.getSecond());

            LocalDateTime dateTimeDa = LocalDateTime.now(clockAuDar);

            System.out.println("Darwin: " + dateTimeDa.getHour() + ":" + dateTimeDa.getMinute() + ":" + dateTimeDa.getSecond());

            System.out.println("---------------------------");

        }


    }
}

Kết luận

Clock class cho đến bây giờ vẫn còn những tính năng riêng của nó tuy nhiên với một người làm software như mình thì ít khi dùng đến, ngoài ra cũng có rất nhiều class khác hỗ trợ Date & Time trong java. Cho đến gần đây thì trong team mới sử dụng nó nhiều để review lại xem chỗ nào đang chạy chậm và tiến hành tối ưu hoá, sau đó tiến hành đo lại để kiểm tra kết quả.

5 1 vote
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x