From fc02de6feec5ec6c18752bc31c1bec8e1a4af256 Mon Sep 17 00:00:00 2001 From: bledi Date: Tue, 8 Feb 2022 11:07:23 +0100 Subject: [PATCH 1/8] Add article How to use CompletableFuture for better performance during API calls --- ...-08-perdormance-with-completable-future.md | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 content/blog/2022/2022-02-08-perdormance-with-completable-future.md diff --git a/content/blog/2022/2022-02-08-perdormance-with-completable-future.md b/content/blog/2022/2022-02-08-perdormance-with-completable-future.md new file mode 100644 index 000000000..d1431266f --- /dev/null +++ b/content/blog/2022/2022-02-08-perdormance-with-completable-future.md @@ -0,0 +1,241 @@ +# How to use CompletableFuture for better performance during API calls + +## What is a Future ? + +The _Future_ is a Java interface that was introduced in Java 5 to represent some value that will be available in a +second moment. The advantages of using it are enormous because we could do some very intensive computation +asynchronously without blocking the Thread that in the meantime can do some other useful job. We can think of it as +going to the restaurant. During the time that the chef is preparing our dinner, we can do other things, like talking to +friends or drinking a glass of wine and when in a second moment the chef has finished the preparation, we can finally +eat. Another advantage is that using the Future interface is much more friendly than working with Threads. + +## CompletableFuture vs. Future + +The Future interface comes with its limitations. Let's see the most important ones : + +- We cannot complete manually the operation by providing a value +- We cannot combine one or more asynchronous operations +- There is no way to react to the completion of the asynchronous operation without blocking the thread by + invoking [get](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()) + method of the _Future_ interface + +All the above limitations are made possible by the new class _CompletableFuture_ that was introduced with +version 8 of Java. CompletableFuture implements both Future +and _[CompletionStage](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html)_ interfaces. +Using this class we can now create a pipeline of asynchronous operations. Let's see a simple example of how to do it : + +```java +class Demo { + public static void main(String[] args) { + + CompletableFuture.supplyAsync(() -> "hello completable future") + .thenApply(String::toUpperCase) + .thenAccept(System.out::println); + } + +} +``` + +In the example above we can notice how simple is to create such a pipeline. We are firstly calling the `supplyAsync` +method which takes a `Supplier` and returns a new CompletableFuture, we are then transforming the result to uppercase +String by calling `thenApply` method and in the end, we just print the value on the console using `thenAccept` that +takes a Consumer as the argument. If we think for a moment, working with CompletableFuture is very similar to Java +Streams. + +## Calling remote APIs without using CompletableFuture (Synchronously) + +In this section we will build a simple application which given a list of bank transactions with call an external service +to categorize the transactions in base of their description. We will simulate the call of the external service by using +a method that adds some delay before returning the category of the transaction. In the next sections we will +incrementally change the implementation of our client application to improve the performance by using CompletableFuture. +Let's start implementing our categorization service that declares a method called `categorizeTransaction` : + +```java +public class CategorizationService { + + public static Category categorizeTransaction(Transaction transaction) { + delay(); + return new Category("Category_" + transaction.getId()); + } + + public static void delay() { + try { + Thread.sleep(1000L); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } +} + +public class Category { + private final String category; + + public Category(String category) { + this.category = category; + } + + @Override + public String toString() { + return "Category{" + + "category='" + category + '\'' + + '}'; + } +} + +public class Transaction { + private String id; + private String description; + + public Transaction(String id, String description) { + this.id = id; + this.description = description; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } +} +``` + +To test this implementation we will build a client application that tries to categorize three transactions, as follows : + +```java +public class Demo { + + public static void main(String[] args) { + long start = System.currentTimeMillis(); + var categories = Stream.of( + new Transaction("1", "description 1"), + new Transaction("2", "description 2"), + new Transaction("3", "description 3")) + .map(CategorizationService::categorizeTransaction) + .collect(Collectors.toList()); + long end = System.currentTimeMillis(); + + System.out.printf("The operation took %s ms%n", end - start); + System.out.println("Categories are: " + categories); + } +} +``` + +After running the code, it prints on the console the total time taken to categorize the three transactions, and on my +machine it is saying : + +``` +The operation took 3039 ms +Categories are: [Category{category='Category_1'}, Category{category='Category_2'}, Category{category='Category_3'}] +``` + +The result is obvious because we are categorizing each transaction in sequence and the time needed to categorize one +transaction is one second. In the next section, we will try to refactor our client application using a parallel Stream. + +## Using parallel Stream to categorize the transactions + +Our client application now looks like : + +```java +public class Demo { + + public static void main(String[] args) { + long start = System.currentTimeMillis(); + var categories = Stream.of( + new Transaction("1", "description 1"), + new Transaction("2", "description 2"), + new Transaction("3", "description 3")) + .parallel() + .map(CategorizationService::categorizeTransaction) + .collect(Collectors.toList()); + long end = System.currentTimeMillis(); + + System.out.printf("The operation took %s ms%n", end - start); + System.out.println("Categories are: " + categories); + } +} +``` + +Is identical like before, apart from that here we are using parallel `Stream`. If we run this method now, it will print +the following output: + +``` +The operation took 1037 ms +Categories are: [Category{category='Category_1'}, Category{category='Category_2'}, Category{category='Category_3'}] +``` + +The difference is huge, now our application runs almost three times faster, but this is not the whole story. This +solution can scale until we reach the limit of the number of processors, after that the performance doesn't change +because internally the parallel Stream use a Thread pool that has a fixed number of threads that is equal to +`Runtime.getRuntime().availableProcessors()`. In my machine, I have 8 processors, so if we run the code above with ten +transactions it will take more than 2 seconds. The out is the following : + +``` +The operation took 2030 ms +Categories are: [Category{category='Category_1'}, Category{category='Category_2'}, Category{category='Category_3'}, +Category{category='Category_4'}, Category{category='Category_5'}, Category{category='Category_6'}, +Category{category='Category_7'}, Category{category='Category_8'}, Category{category='Category_9'}, Category{category='Category_10'}] +``` + +We see that the operation took 2030 ms, as predicted. Can we do something to increase even more the performance of our +application? YES! + +## Using CompletableFuture with a custom Executor + +Now will refactor our client application to take advantage of CompletableFuture and because we have now ten transactions +to categorize, we will use an `Executor` with a fixed thread pool of ten Threads. + +```java +public class Demo { + + public static void main(String[] args) { + Executor executor = Executors.newFixedThreadPool(10); + long start = System.currentTimeMillis(); + var futureCategories = Stream.of( + new Transaction("1", "description 1"), + new Transaction("2", "description 2"), + new Transaction("3", "description 3"), + new Transaction("4", "description 4"), + new Transaction("5", "description 5"), + new Transaction("6", "description 6"), + new Transaction("7", "description 7"), + new Transaction("8", "description 8"), + new Transaction("9", "description 9"), + new Transaction("10", "description 10") + ) + .map(transaction -> CompletableFuture.supplyAsync(() -> CategorizationService.categorizeTransaction(transaction), executor)) + .collect(toList()); + + var categories = futureCategories.stream() + .map(CompletableFuture::join) + .collect(toList()); + long end = System.currentTimeMillis(); + + System.out.printf("The operation took %s ms%n", end - start); + System.out.println("Categories are: " + categories); + } +} +``` + +Our client application is trying to call the categorization service by using the method `supplyAsync` that takes as +arguments a `Supplier` and an `Executor`. Because now we have ten transactions and a custom Executor that has a pool of +ten threads, we expect that the operation should take around one second. Indeed, the output confirms the expected +result : + +``` +The operation took 1040 ms +Categories are: [Category{category='Category_1'}, Category{category='Category_2'}, Category{category='Category_3'}, +Category{category='Category_4'}, Category{category='Category_5'}, Category{category='Category_6'}, +Category{category='Category_7'}, Category{category='Category_8'}, Category{category='Category_9'}, Category{category='Category_10'}] +``` + + From 94f2aca1f01e11f919e433903cfb68b37e57e4ff Mon Sep 17 00:00:00 2001 From: bledi Date: Tue, 8 Feb 2022 11:08:27 +0100 Subject: [PATCH 2/8] Revert "Add article How to use CompletableFuture for better performance during API calls" This reverts commit fc02de6feec5ec6c18752bc31c1bec8e1a4af256. --- ...-08-perdormance-with-completable-future.md | 241 ------------------ 1 file changed, 241 deletions(-) delete mode 100644 content/blog/2022/2022-02-08-perdormance-with-completable-future.md diff --git a/content/blog/2022/2022-02-08-perdormance-with-completable-future.md b/content/blog/2022/2022-02-08-perdormance-with-completable-future.md deleted file mode 100644 index d1431266f..000000000 --- a/content/blog/2022/2022-02-08-perdormance-with-completable-future.md +++ /dev/null @@ -1,241 +0,0 @@ -# How to use CompletableFuture for better performance during API calls - -## What is a Future ? - -The _Future_ is a Java interface that was introduced in Java 5 to represent some value that will be available in a -second moment. The advantages of using it are enormous because we could do some very intensive computation -asynchronously without blocking the Thread that in the meantime can do some other useful job. We can think of it as -going to the restaurant. During the time that the chef is preparing our dinner, we can do other things, like talking to -friends or drinking a glass of wine and when in a second moment the chef has finished the preparation, we can finally -eat. Another advantage is that using the Future interface is much more friendly than working with Threads. - -## CompletableFuture vs. Future - -The Future interface comes with its limitations. Let's see the most important ones : - -- We cannot complete manually the operation by providing a value -- We cannot combine one or more asynchronous operations -- There is no way to react to the completion of the asynchronous operation without blocking the thread by - invoking [get](https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#get()) - method of the _Future_ interface - -All the above limitations are made possible by the new class _CompletableFuture_ that was introduced with -version 8 of Java. CompletableFuture implements both Future -and _[CompletionStage](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html)_ interfaces. -Using this class we can now create a pipeline of asynchronous operations. Let's see a simple example of how to do it : - -```java -class Demo { - public static void main(String[] args) { - - CompletableFuture.supplyAsync(() -> "hello completable future") - .thenApply(String::toUpperCase) - .thenAccept(System.out::println); - } - -} -``` - -In the example above we can notice how simple is to create such a pipeline. We are firstly calling the `supplyAsync` -method which takes a `Supplier` and returns a new CompletableFuture, we are then transforming the result to uppercase -String by calling `thenApply` method and in the end, we just print the value on the console using `thenAccept` that -takes a Consumer as the argument. If we think for a moment, working with CompletableFuture is very similar to Java -Streams. - -## Calling remote APIs without using CompletableFuture (Synchronously) - -In this section we will build a simple application which given a list of bank transactions with call an external service -to categorize the transactions in base of their description. We will simulate the call of the external service by using -a method that adds some delay before returning the category of the transaction. In the next sections we will -incrementally change the implementation of our client application to improve the performance by using CompletableFuture. -Let's start implementing our categorization service that declares a method called `categorizeTransaction` : - -```java -public class CategorizationService { - - public static Category categorizeTransaction(Transaction transaction) { - delay(); - return new Category("Category_" + transaction.getId()); - } - - public static void delay() { - try { - Thread.sleep(1000L); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } -} - -public class Category { - private final String category; - - public Category(String category) { - this.category = category; - } - - @Override - public String toString() { - return "Category{" + - "category='" + category + '\'' + - '}'; - } -} - -public class Transaction { - private String id; - private String description; - - public Transaction(String id, String description) { - this.id = id; - this.description = description; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } -} -``` - -To test this implementation we will build a client application that tries to categorize three transactions, as follows : - -```java -public class Demo { - - public static void main(String[] args) { - long start = System.currentTimeMillis(); - var categories = Stream.of( - new Transaction("1", "description 1"), - new Transaction("2", "description 2"), - new Transaction("3", "description 3")) - .map(CategorizationService::categorizeTransaction) - .collect(Collectors.toList()); - long end = System.currentTimeMillis(); - - System.out.printf("The operation took %s ms%n", end - start); - System.out.println("Categories are: " + categories); - } -} -``` - -After running the code, it prints on the console the total time taken to categorize the three transactions, and on my -machine it is saying : - -``` -The operation took 3039 ms -Categories are: [Category{category='Category_1'}, Category{category='Category_2'}, Category{category='Category_3'}] -``` - -The result is obvious because we are categorizing each transaction in sequence and the time needed to categorize one -transaction is one second. In the next section, we will try to refactor our client application using a parallel Stream. - -## Using parallel Stream to categorize the transactions - -Our client application now looks like : - -```java -public class Demo { - - public static void main(String[] args) { - long start = System.currentTimeMillis(); - var categories = Stream.of( - new Transaction("1", "description 1"), - new Transaction("2", "description 2"), - new Transaction("3", "description 3")) - .parallel() - .map(CategorizationService::categorizeTransaction) - .collect(Collectors.toList()); - long end = System.currentTimeMillis(); - - System.out.printf("The operation took %s ms%n", end - start); - System.out.println("Categories are: " + categories); - } -} -``` - -Is identical like before, apart from that here we are using parallel `Stream`. If we run this method now, it will print -the following output: - -``` -The operation took 1037 ms -Categories are: [Category{category='Category_1'}, Category{category='Category_2'}, Category{category='Category_3'}] -``` - -The difference is huge, now our application runs almost three times faster, but this is not the whole story. This -solution can scale until we reach the limit of the number of processors, after that the performance doesn't change -because internally the parallel Stream use a Thread pool that has a fixed number of threads that is equal to -`Runtime.getRuntime().availableProcessors()`. In my machine, I have 8 processors, so if we run the code above with ten -transactions it will take more than 2 seconds. The out is the following : - -``` -The operation took 2030 ms -Categories are: [Category{category='Category_1'}, Category{category='Category_2'}, Category{category='Category_3'}, -Category{category='Category_4'}, Category{category='Category_5'}, Category{category='Category_6'}, -Category{category='Category_7'}, Category{category='Category_8'}, Category{category='Category_9'}, Category{category='Category_10'}] -``` - -We see that the operation took 2030 ms, as predicted. Can we do something to increase even more the performance of our -application? YES! - -## Using CompletableFuture with a custom Executor - -Now will refactor our client application to take advantage of CompletableFuture and because we have now ten transactions -to categorize, we will use an `Executor` with a fixed thread pool of ten Threads. - -```java -public class Demo { - - public static void main(String[] args) { - Executor executor = Executors.newFixedThreadPool(10); - long start = System.currentTimeMillis(); - var futureCategories = Stream.of( - new Transaction("1", "description 1"), - new Transaction("2", "description 2"), - new Transaction("3", "description 3"), - new Transaction("4", "description 4"), - new Transaction("5", "description 5"), - new Transaction("6", "description 6"), - new Transaction("7", "description 7"), - new Transaction("8", "description 8"), - new Transaction("9", "description 9"), - new Transaction("10", "description 10") - ) - .map(transaction -> CompletableFuture.supplyAsync(() -> CategorizationService.categorizeTransaction(transaction), executor)) - .collect(toList()); - - var categories = futureCategories.stream() - .map(CompletableFuture::join) - .collect(toList()); - long end = System.currentTimeMillis(); - - System.out.printf("The operation took %s ms%n", end - start); - System.out.println("Categories are: " + categories); - } -} -``` - -Our client application is trying to call the categorization service by using the method `supplyAsync` that takes as -arguments a `Supplier` and an `Executor`. Because now we have ten transactions and a custom Executor that has a pool of -ten threads, we expect that the operation should take around one second. Indeed, the output confirms the expected -result : - -``` -The operation took 1040 ms -Categories are: [Category{category='Category_1'}, Category{category='Category_2'}, Category{category='Category_3'}, -Category{category='Category_4'}, Category{category='Category_5'}, Category{category='Category_6'}, -Category{category='Category_7'}, Category{category='Category_8'}, Category{category='Category_9'}, Category{category='Category_10'}] -``` - - From c99b5dfa1c71738f95d5fb80a1922d81dc846049 Mon Sep 17 00:00:00 2001 From: bledi Date: Sun, 27 Feb 2022 12:31:33 +0100 Subject: [PATCH 3/8] Adding image and title of the article --- .../blog/2022/2022-02-27-working-with-dates-in-java.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 content/blog/2022/2022-02-27-working-with-dates-in-java.md diff --git a/content/blog/2022/2022-02-27-working-with-dates-in-java.md b/content/blog/2022/2022-02-27-working-with-dates-in-java.md new file mode 100644 index 000000000..dfde9fdc9 --- /dev/null +++ b/content/blog/2022/2022-02-27-working-with-dates-in-java.md @@ -0,0 +1,10 @@ +--- +title: "Working with Dates in Java" +categories: ["Java"] +date: 2022-02-27 00:00:00 +1100 +authors: ["nukajbl"] +excerpt: "In this article, we will explore the new Java time API and will learn how to use the new classes that are +located on java.time package." +image: images/stock/0111-clock-1200x628-branded.jpg +url: java-date +--- \ No newline at end of file From 1210227f11d0a87f31db0ffea68c9dbe71f3c151 Mon Sep 17 00:00:00 2001 From: bledi Date: Sat, 12 Mar 2022 15:28:47 +0100 Subject: [PATCH 4/8] Add outline --- .../2022-02-27-working-with-dates-in-java.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/content/blog/2022/2022-02-27-working-with-dates-in-java.md b/content/blog/2022/2022-02-27-working-with-dates-in-java.md index dfde9fdc9..cd022b681 100644 --- a/content/blog/2022/2022-02-27-working-with-dates-in-java.md +++ b/content/blog/2022/2022-02-27-working-with-dates-in-java.md @@ -7,4 +7,21 @@ excerpt: "In this article, we will explore the new Java time API and will learn located on java.time package." image: images/stock/0111-clock-1200x628-branded.jpg url: java-date ---- \ No newline at end of file +--- +## Working With `LocalDate` +### Different Ways To Create a `LocalDate` Object +### `LocalDate` Arithmetic +### Formatting a `LocalDate` Object + +## Working With `LocalTime` +### Different Ways To Create a `LocalTime` Object +### `LocalTime` Arithmetic +### Formatting a `LocalTime` Object + +## Working With `LocalDateTime` +### Different Ways To Create a `LocalDateTime` Object +### `LocalDateTime` Arithmetic +### Formatting a `LocalDateTime` Object + +## Working With `Instant` and `Duration` +## Working With Different Time Zones From 6388afdc74c8cc4ccfa72cf590439b2157dde7ec Mon Sep 17 00:00:00 2001 From: bledi Date: Tue, 15 Mar 2022 21:55:52 +0100 Subject: [PATCH 5/8] Adding LocalDate part of the article --- .../2022-02-27-working-with-dates-in-java.md | 154 +++++++++++++++++- 1 file changed, 152 insertions(+), 2 deletions(-) diff --git a/content/blog/2022/2022-02-27-working-with-dates-in-java.md b/content/blog/2022/2022-02-27-working-with-dates-in-java.md index cd022b681..c510743c9 100644 --- a/content/blog/2022/2022-02-27-working-with-dates-in-java.md +++ b/content/blog/2022/2022-02-27-working-with-dates-in-java.md @@ -4,13 +4,163 @@ categories: ["Java"] date: 2022-02-27 00:00:00 +1100 authors: ["nukajbl"] excerpt: "In this article, we will explore the new Java time API and will learn how to use the new classes that are -located on java.time package." +located on `java.time` package." image: images/stock/0111-clock-1200x628-branded.jpg url: java-date --- + +In this article, we will learn how to properly use the new Java API for manipulating Date and Time. In particular, we +will explore `LocalDate`, `LocalTime`, `LocalDateTime`, `Instant` and `Duration`. All the mentioned classes are +immutable, once created the instance, cannot be changed. A famous immutable class in Java is the `String` class. + ## Working With `LocalDate` -### Different Ways To Create a `LocalDate` Object + +`LocalDate` is the most used class from the new API. It represents a date without any information about the time. Like +we mentioned above, this is an immutable class and has, so any operation on it will return a new instance with the new +value. + +### How To Create a `LocalDate` Object + +To create an instance of the `LocalDate` class, we can use one of the static factory methods `of()`, like in the sample +below. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, 3, 13); + System.out.println("The date is: " + date); + } +} +``` + +Here we have an object of type `LocalDate` that represents the 13 March 2022. The first argument is the year, the +second the month and the third is the day. If we try to run the `main()` method, it will print the following +information: + +`The date is: 2022-03-13` + +There is an overloaded version of this method that instead of the index of the month, takes an instance of the `Month` +enum. We can write the same example as: + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, Month.MARCH, 13); + System.out.println("The date is: " + date); + } +} +``` + +In case we would like to get the current date, we can use the static method `now()`: + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate currentDate = LocalDate.now(); + } +} +``` + +When we need to get some information about the date, like the year, the month or the day of the month, we can use the +methods `getYear()`, `getMonth()` and `getDayOfMonth()`. Let's see how to use these methods with an example. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, Month.MARCH, 13); + int year = date.getYear(); + Month month = date.getMonth(); + int day = date.getDayOfMonth(); + } +} +``` + +Exists another method to get the same information by passing a `TemporalField` and is called `get()`. Using this method, +let's try to gather the same information as in the example above: + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, Month.MARCH, 13); + int year = date.get(ChronoField.YEAR); + int month = date.get(ChronoField.MONTH_OF_YEAR); + int day = date.get(ChronoField.DAY_OF_MONTH); + } +} +``` + +The `ChronoField` is an enumeration that implements the `TemporalField` interface. It has different elements, in our +case we have just used three of them: `ChronoField.YEAR`, `ChronoField.MONTH_OF_YEAR` and `ChronoField.DAY_OF_MONTH` to +get the information about the year, month and day. + +### Parsing a `LocalDate` Object + +When working with dates, very often we need to parse a `String` representation and create an instance of `LocalDate` +class. We can use the method `parse()` to achieve this. This method takes as arguments the date we want to parse and an +instance of `DateTimeFormatter`. The class `DateTimeFormatter` can be found at `java.time.format` package. The instances +of this class are now thread-safe. Let's see an example of how it works. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.parse("2022-03-13", DateTimeFormatter.ISO_LOCAL_DATE); + System.out.println("The date is: " + date); + } +} +``` + +In this case, we are using `ISO_LOCAL_DATE` which is a predefined instance of the `DateTimeFormatter` class. If we want +a custom formatter, we can create our own by using the static method `ofPattern()`, like shown below. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + LocalDate date = LocalDate.parse("13/03/2022", dateTimeFormatter); + System.out.println("The date is: " + date); + } +} +``` + +Here we have used the static method `ofPattern()` of the `DateFormatter` class passing the pattern `dd/MM/yyyy`. Using +this pattern, we have created a LocalDate instance which is the representation of the string `13/03/2022`. + ### `LocalDate` Arithmetic + +To manipulate a LocalDate instance, we can use one of the methods this class offers. To mention some of these methods, +we can use `withYear()` which changes the year part of the date. Another method is `withDayOfMonth()` which of course +changes the day of the month. +To understand better, let's look at the following example. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, 3, 13); // 2022-3-13 + LocalDate date2 = date.withYear(2021); // 2021-3-13 + LocalDate date3 = date.withDayOfMonth(24); // 2022-3-24 + LocalDate date4 = date.withMonth(5); // 2022-5-13 + } +} +``` + +In the first line, we have created an instance of `LocalDate` class that we will manipulate in the next lines. In the +second line, we have changed the year by using `withYear()` method. In the third line, we have changed the day of the +month by using the method `withDayOfMonth()`, so now the day is 24 and not anymore 13, like the original one. And +finally, we have changed the month by using the method `withMonth()`. +Exist a more generic method which is called `with()` that takes as first argument a `TemporalField`. +We will use the same example as above, but now using only the generic method `with()`. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, 3, 13); + LocalDate date2 = date.with(ChronoField.YEAR,2021); // 2021-3-13 + LocalDate date3 = date.with(ChronoField.DAY_OF_MONTH,24); // 2022-3-24 + LocalDate date4 = date.with(ChronoField.MONTH_OF_YEAR,5); // 2022-5-13 + } +} +``` + ### Formatting a `LocalDate` Object ## Working With `LocalTime` From 12dc07ded5d5708e481a0838beb16e48ade224db Mon Sep 17 00:00:00 2001 From: bledi Date: Tue, 15 Mar 2022 22:30:21 +0100 Subject: [PATCH 6/8] Add Formatting section for LocalDate --- .../2022-02-27-working-with-dates-in-java.md | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/content/blog/2022/2022-02-27-working-with-dates-in-java.md b/content/blog/2022/2022-02-27-working-with-dates-in-java.md index c510743c9..269e7bdde 100644 --- a/content/blog/2022/2022-02-27-working-with-dates-in-java.md +++ b/content/blog/2022/2022-02-27-working-with-dates-in-java.md @@ -163,13 +163,46 @@ public class DateAndTimeDemo { ### Formatting a `LocalDate` Object +If we want a string representation of an `LocalDate` object, we can use the method `format()` which takes as argument +a `DateTimeFormatter`. Like mentioned in the other sections above, exists predefined instances of the +class `DateTimeFormatter` like `BASIC_ISO_DATE` or `ISO_LOCAL_DATE`. +instances to format a date. +In the list below, we will use these instances to format a date. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, 3, 13); + System.out.println(date.format(DateTimeFormatter.BASIC_ISO_DATE)); // 20220313 + System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2022-03-13 + } +} +``` + +We can even create our own formatter by using the static method `ofPattern()` of the class `DateTimeFormatter`. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, 3, 13); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); + System.out.println(date.format(formatter)); // 13/03/2022 + } +} +``` + +Here we have used a custom formatter of pattern `dd/MM/yyyy`. When we print the date on the console, the output +is `13/03/2022`, as expected to be. + ## Working With `LocalTime` -### Different Ways To Create a `LocalTime` Object +### How To Create a `LocalTime` Object +### Parsing a `LocalTime` Object ### `LocalTime` Arithmetic ### Formatting a `LocalTime` Object ## Working With `LocalDateTime` -### Different Ways To Create a `LocalDateTime` Object +### How To Create a `LocalDateTime` Object +### Parsing a `LocalDateTime` Object ### `LocalDateTime` Arithmetic ### Formatting a `LocalDateTime` Object From ee5b305ba17fbc359c31de3cc669674413ddafa4 Mon Sep 17 00:00:00 2001 From: bledi Date: Fri, 18 Mar 2022 23:38:59 +0100 Subject: [PATCH 7/8] Add LocalTime and LocalDateTime --- .../2022-02-27-working-with-dates-in-java.md | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) diff --git a/content/blog/2022/2022-02-27-working-with-dates-in-java.md b/content/blog/2022/2022-02-27-working-with-dates-in-java.md index 269e7bdde..6cb8aa561 100644 --- a/content/blog/2022/2022-02-27-working-with-dates-in-java.md +++ b/content/blog/2022/2022-02-27-working-with-dates-in-java.md @@ -195,15 +195,265 @@ Here we have used a custom formatter of pattern `dd/MM/yyyy`. When we print the is `13/03/2022`, as expected to be. ## Working With `LocalTime` + +An instance of `LocalTime` holds the information about the time but not of the date. Let's see how to create an instance +of `LocalTime`. + ### How To Create a `LocalTime` Object + +To create an instance of the `LocalTime` class, we can use one of the static factory methods `of()`, like in the sample +below. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time = LocalTime.of(22, 33, 13); + System.out.println("The time is: " + time); // The time is: 22:33:13 + } +} +``` + +Here we have an object of type `LocalTime`. The first argument is the hour, the +second are the minutes, and the third are the seconds. + +In case we would like to get the current time, we can use the static method `now()`: + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time = LocalTime.now(); + } +} +``` + +When we need to get some information about the time, like the hour, the minutes or the seconds, we can use the +methods `getHour()`, `getMinute()` and `getSecond()`. Let's see how to use these methods with an example. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time = LocalTime.of(22, 13, 45); + int hour = time.getHour(); // 22 + int minute = time.getMinute(); // 13 + int second = time.getSecond(); // 45 + } +} +``` + +Exists another method to get the same information by passing a `TemporalField` and is called `get()`. Using this method, +let's try to gather the same information as in the example above: + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time = LocalTime.of(22, 13, 45); + int hour = time.get(ChronoField.HOUR_OF_DAY); // 22 + int minute = time.get(ChronoField.MINUTE_OF_HOUR); // 13 + int second = time.get(ChronoField.SECOND_OF_MINUTE); // 45 + } +} +``` + +The `ChronoField` is an enumeration that implements the `TemporalField` interface. It has different elements, in our +case we have just used three of them: `ChronoField.HOUR_OF_DAY`, `ChronoField.MINUTE_OF_HOUR` +and `ChronoField.SECOND_OF_MINUTE` to get the information about the hour, minute and second. + ### Parsing a `LocalTime` Object + +When we need to parse a `String` representation and create an instance of `LocalTime` +class. We can use the method `parse()` to achieve this. This method takes as arguments the time we want to parse and an +instance of `DateTimeFormatter`. The class `DateTimeFormatter` can be found at `java.time.format` package. Let's see an +example of how it works. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time = LocalTime.parse("22:12:45", DateTimeFormatter.ISO_LOCAL_TIME); + System.out.println("The time is: " + time); // The time is: 22:12:45 + } +} +``` + +In this case, we are using `ISO_LOCAL_TIME` which is a predefined instance of the `DateTimeFormatter` class. If we want +a custom formatter, we can create our own by using the static method `ofPattern()`, like shown below. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("H:mm:ss"); + LocalTime time = LocalTime.parse("3:30:45", dateTimeFormatter); + System.out.println("The time is: " + time); // The date is: 03:30:45 + } +} +``` + +Here we have used the static method `ofPattern()` of the `DateFormatter` class passing the pattern `H:mm:ss`. Using +this pattern, we have created a LocalTime instance which is the representation of the string `3:30:45`. + ### `LocalTime` Arithmetic + +To manipulate a `LocalTime` instance, we can use one of the methods this class offers. To mention some of these methods, +we can use `withHour()` which changes the hour part of the time. Another method is `withMinute()` which changes the +minute part. To understand better, let's look at the following example. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time = LocalTime.of(22, 13, 45); // 22:13:45 + LocalTime time2 = time.withHour(21); // 21:13:45 + LocalTime time3 = time.withMinute(10); // 22:10:45 + LocalTime time4 = time.withSecond(20); // 22:13:20 + } +} +``` + +Using the `LocalTime` class, we created an instance in the first line that we will manipulate in the following lines. In +the second line, we changed the hour by using the `withHour()` method. In the third line, we changed the minute part by +using the `withMinute()` method and in the last line we changed the seconds by calling the method `withSecond()`. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.of(2022, 3, 13); + LocalDate date2 = date.with(ChronoField.YEAR,2021); // 2021-3-13 + LocalDate date3 = date.with(ChronoField.DAY_OF_MONTH,24); // 2022-3-24 + LocalDate date4 = date.with(ChronoField.MONTH_OF_YEAR,5); // 2022-5-13 + } +} +``` + ### Formatting a `LocalTime` Object +An `LocalTime` object can be formatted using the method `format()`, which takes as argument a `DateTimeFormatter`. +Exist predefined instances of the class `DateTimeFormatter` such as `ISO_LOCAL_TIME` or `ISO_TIME`. +These instances will be used to format a time based on the list below. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time = LocalTime.of(22, 43, 25); + System.out.println(time.format(DateTimeFormatter.ISO_LOCAL_TIME)); // 22:43:25 + System.out.println(time.format(DateTimeFormatter.ISO_TIME)); // 22:43:25 + } +} +``` + +The static method `ofPattern()` in the class `DateTimeFormatter` can also be used to create our own formatter. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time = LocalTime.of(22, 13, 43); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH.mm.ss"); + System.out.println(time.format(formatter)); // 22.13.43 + } +} +``` + +We are using the custom formatter `HH.mm.ss` here. When we print the time on the console, we get `22.13.43` as expected. + ## Working With `LocalDateTime` + +Up to this point, we have learned how to create instances of the classes `LocalDate` and `LocalTime`. In this section, +we will learn how to combine the two classes into one, called `LocalDatetime`. + ### How To Create a `LocalDateTime` Object + +As shown below, we can create an instance of the `LocalDateTime` class with one of its static factory methods `of()`. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDateTime localDateTime = LocalDateTime.of(2022, 3, 13, 22, 13, 45); // The date and time is: 2022-03-13T22:13:45 + System.out.println("The date and time is: " + localDateTime); + } +} +``` + +An object of type `LocalDateTime` represents 13 March 2022 at 22:13:45. The year, the month, and the date are the first +three arguments, while the hour, the minute, and the seconds are the other three. + +The static method `now()` can be used to retrieve the current date: + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDateTime now = LocalDateTime.now(); + } +} +``` + +We can use the methods `getYear()`, `getMonth()` and `getDayOfMonth()` to get information about the date, such as the +year, the month or the day of the month. Let's see how they work with an example. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDateTime dateTime = LocalDateTime.of(2022, Month.MARCH, 13, 22, 13, 45); + int year = dateTime.getYear(); + Month month = dateTime.getMonth(); + int day = dateTime.getDayOfMonth(); + int hour = time.getHour(); + int minute = time.getMinute(); + int second = time.getSecond(); + } +} +``` + +There is another method to get the same information by passing a `TemporalField`. This method is called `get()`. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDateTime dateTime = LocalDateTime.of(2022, Month.MARCH, 13, 22, 13, 45); + int year = date.get(ChronoField.YEAR); + int month = date.get(ChronoField.MONTH_OF_YEAR); + int day = date.get(ChronoField.DAY_OF_MONTH); + int hour = time.get(ChronoField.HOUR_OF_DAY); + int minute = time.get(ChronoField.MINUTE_OF_HOUR); + int second = time.get(ChronoField.SECOND_OF_MINUTE); + } +} +``` + +The `ChronoField` is an enumeration that implements the `TemporalField` interface. It consists of different elements, in +our case we have used some of them: `ChronoField.YEAR`, `ChronoField.MONTH_OF_YEAR` and `ChronoField.DAY_OF_MONTH` to +get the information about the year, month and day. + ### Parsing a `LocalDateTime` Object + +In order to work with dates, we may need to parse a string representation and create an instance of the `LocalDateTime` +class using the method `parse()`. This method takes a date and an instance of a `DateTimeFormatter` as arguments. +Here is an example of how to use the class `DateTimeFormatter` from the `java.time.format` package. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDate date = LocalDate.parse("2022-03-13", DateTimeFormatter.ISO_LOCAL_DATE); + System.out.println("The date is: " + date); + } +} +``` + +In this case, we are using `ISO_LOCAL_DATE` which is a predefined instance of the `DateTimeFormatter` class. If we want +a custom formatter, we can create our own by using the static method `ofPattern()`, like shown below. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy H.mm.ss"); + LocalDateTime dateTime = LocalDateTime.parse("13/03/2022 22.43.14", dateTimeFormatter); + System.out.println("The date and time are: " + dateTime); // The date and time are: 2022-03-13T22:43:14 + } +} +``` + +As shown here, we used the static method `ofPattern()` of the `DateFormatter` class, passing the string `dd/MM/yyyy H.mm.ss`. +Using this pattern, we create a `LocalDateTime` instance, which represents the string `13/03/2022 22.43.14`. + ### `LocalDateTime` Arithmetic + + ### Formatting a `LocalDateTime` Object ## Working With `Instant` and `Duration` From cb96f5c77a4b6915349bab927a2d2bdcaaf4d389 Mon Sep 17 00:00:00 2001 From: bledi Date: Sun, 20 Mar 2022 17:47:31 +0100 Subject: [PATCH 8/8] add duration and period --- .../2022-02-27-working-with-dates-in-java.md | 91 ++++++++++++++++++- 1 file changed, 89 insertions(+), 2 deletions(-) diff --git a/content/blog/2022/2022-02-27-working-with-dates-in-java.md b/content/blog/2022/2022-02-27-working-with-dates-in-java.md index 6cb8aa561..72e6f3e96 100644 --- a/content/blog/2022/2022-02-27-working-with-dates-in-java.md +++ b/content/blog/2022/2022-02-27-working-with-dates-in-java.md @@ -453,8 +453,95 @@ Using this pattern, we create a `LocalDateTime` instance, which represents the s ### `LocalDateTime` Arithmetic +The `LocalDateTime` class provides several methods for manipulating dates. One of these is `withYear()`, which changes +the year part of the date. Another method is `withDayOfMonth()`, which changes the month part of the date. +Let's examine the following example to better understand. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDateTime date = LocalDateTime.of(2022, 1, 13, 15, 47, 54); // 2022-01-13 15:47:54 + LocalDateTime date2 = date.withYear(2021); // 2021-01-13 15:47:54 + LocalDateTime date3 = date.withDayOfMonth(24); // 2022-01-24 15:47:54 + LocalDateTime date4 = date.withMonth(5); // 2022-05-13 15:47:54 + LocalDateTime date5 = date.withHour(12); // 2022-01-13 12:47:54 + LocalDateTime date6 = date.withMinute(32); // 2022-01-13 12:47:32 + } +} +``` + +We began by creating an instance of the `LocalDateTime` object and on each successive row, we changed some property of +it. First, we changed the year by calling the method `withYear()`, and then we changed the month by using the method +`withDayOfMonth()`. We had changed the time part of our object by calling the three methods that we learnt when we saw +how to format a LocalTime object. ### Formatting a `LocalDateTime` Object -## Working With `Instant` and `Duration` -## Working With Different Time Zones +String representations of `LocalDateTime` objects can be created with the method `format()`, which takes +a `DateTimeFormatter` argument. As mentioned earlier, we can find predefined instances of the `DateTimeFormatter` class +such as `ISO_LOCAL_DATE_TIME` or `ISO_ORDINAL_DATE` instances to format a date. We're going to use these instances to +format the date in the list below. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDateTime localDateTime = LocalDateTime.now(); + localDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); // 2022-03-20T15:56:30.566388 + localDateTime.format(DateTimeFormatter.ISO_ORDINAL_DATE); // 2022-03-20T15:56:30.566388 + } +} +``` + +The class `DateTimeFormatter` provides a static method named `ofPattern()` that we can use to create our own formatter. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalDateTime dateTime = LocalDateTime.of(2022, 2, 13, 16, 23, 45); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy H%mm%ss"); // 13/02/2022 16%23%45 + } +} +``` + +In this case, we used a custom format of pattern `dd/MM/yyyy H%mm%ss`. When we print the date on the console, we get the +expected result of 1`3/02/2022 16%23%45`. + + +## Working With `Duration` and `Period` + +Through the use of the 'Duration' class, we can measure the difference in seconds and eventually nanoseconds between two +temporal objects. With the help of the static method called `between()` we can calculate the difference. This method is +able to accept instances of the `Instant` class, the `LocalTime` class, and the `LocalDateTime` class. +Let's see an example to understand better. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + LocalTime time1 = LocalTime.of(15, 47, 54); + LocalTime time2 = LocalTime.of(15, 47, 56); + Duration duration = Duration.between(time1, time2); + System.out.println(duration.getSeconds()); // 2 + } +} +``` +This code creates two instances of the `LocalTime` class. +We then create a Duration instance and measure the difference between `time1` and `time2`. In this case, the value is 2. +Due to the fact that the Duration class expresses the difference in seconds between two temporal objects, but the +LocalDate class does not contain time information, we cannot use the Duration class with instances of `LocalDate`. + +When we need to express an amount of time as years, months, and days, then `Period` is the class we need. +Let's see how to create such instances. + + ```java +public class DateAndTimeDemo { + public static void main(String[] args) { + Period periodOfOneWeek = Period.ofWeeks(1); + Period periodOfTwoDays = Period.ofDays(2); + Period periodOfOneMonth = Period.ofMonths(1), + } +} +``` + +Through the static methods `ofWeek()`,` ofDay()`, and `ofMonth()` that are provided by the `Period` class, we created +three different objects. The first object represents the period of one week, the second the period of two days and the +last one month. \ No newline at end of file