# Reading byte array into float (expanding on SerialCallResponse example)

**URL:** https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880
**Category:** Electronics (Arduino, etc.)
**Created:** [January 5, 2020, 7:09pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880 "2020-01-05T19:09:08Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 5, 2020, 7:09pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/1 "2020-01-05T19:09:08Z")

</div>

An old C programmer, I’m new to Processing (and not particularly skilled at C++, come to that…), so naturally I’m banging up against the stronger type discipline of Object Oriented languages, and could use a spot of help…  
I’m writing code based on the Arduino/Processing example pair “SerialCallResponse”, which transfers bytes on request.  
Instead of simple bytes/integers, want to transfer floats in my data. Sending them from Arduino is simple (a simple union of 4 bytes and a float was all I needed to feed Serial.write()), but how to I read four bytes from Processing’s receive buffer into a float?

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [January 5, 2020, 8:24pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/2 "2020-01-05T20:24:02Z")

</div>

> [@julianop](#):
>
> , but how do I read four bytes from Processing’s receive buffer into a `float`?

- [Transmission of a float through a serial link - Processing 2.x and 3.x Forum](http://Forum.Processing.org/two/discussion/12757/transmission-of-a-float-through-a-serial-link#Item_4)

> [@Float value to Byte array](https://discourse.processing.org/t/float-value-to-byte-array/16698/3):
>
> This is my take on it for both opposite conversion ways. left_right_arrow You can also take a look at this site below in order to double-check results: heavy_check_mark[H-Schmidt.net/FloatConverter/IEEE754.html](http://H-Schmidt.net/FloatConverter/IEEE754.html)[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Float.html#floatToIntBits(float)](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Float.html#floatToIntBits(float)) /\*\* \* Float As Bytes Array (v1.1.1) \* GoToLoop (2019/Dec/29) \* https://Discourse.Processing.org/t/float-value-to-byte-array/16698/3 \*/ static final float MY\_FLOAT = -PI; byte[] fl…

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 5, 2020, 9:02pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/3 "2020-01-05T21:02:04Z")

</div>

Excellent, thank you.

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 5, 2020, 9:05pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/4 "2020-01-05T21:05:44Z")

</div>

In a related question - and please forgive my ignorance of what probably appears basic…  
In C I could pass a pointer to an integer (i.e. a primitive, not an object) to a function and have that function increment it (fairly obviously I’m talking about an array index). As Java doesn’t work that way (as well described here  
[http://www.javadude.com/articles/passbyvalue.htm](http://www.javadude.com/articles/passbyvalue.htm)  
how would I achieve the same functionalilty?

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [January 5, 2020, 9:11pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/5 "2020-01-05T21:11:05Z")

</div>

> [@julianop](#):
>
> How would I achieve the same functionality?

Either you `return` the value and assign it to the variable you wanna mutate or… use an object, which can be freely mutated.

For the latter, you can for example pass an `int[]` array instead of a vanilla `int`.

P.S.: Almost forgot: Declare a global field, so it can be reassigned everywhere! 🌐

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 5, 2020, 11:42pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/6 "2020-01-05T23:42:01Z")

</div>

Ah, so simply making it an array - even if it’s a single element array - promotes it from primitive to object class, so that the “pass by reference” opportunity exists; I get it 🙂  
Global - got that too.  
Thanks again:-)

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 6, 2020, 12:52am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/7 "2020-01-06T00:52:07Z")

</div>

OK, so I seem to have misunderstood the concept of marking a post as a solution. GoToLoop provided my solution, I didn’t.

---

<div class="post-metadata">

### Author: ![kll](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/kll/32/964_2.png) [@kll](https://discourse.processing.org/u/kll)
#### Post date: [January 6, 2020, 12:53am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/8 "2020-01-06T00:53:34Z")

</div>

yes, you can change that by click on the correct post.

---

<div class="post-metadata">

### Author: ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)
#### Post date: [January 6, 2020, 8:40pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/9 "2020-01-06T20:40:50Z")

</div>

> [@julianop](#):
>
> from primitive to object class, so that the “pass by reference” opportunity exists

Just to clarify, you are still passing a value – the value is a pointer to an array (or an Object).

This matters because the pointer destination can be modified, but the receiving function can’t reassign things to the reference label that was used to pass that value, because it doesn’t have that reference – it only has the pointer value.

```auto
void setup() {
  int[] a = new int[]{0, 0};
  increase(a); // yes -- can modify by passing value of array pointer
  println(a); // {0, 1}
  replace(a); // no -- cannot point 'a' at new contents, reference not passed
  println(a); // {0, 1} -- not {9, 9}
}

void increase(int[] i) { // succeeds, value is pointer
  i[1] = i[1]+1;
}

void replace(int[] i) { // fails, not pass by reference so cannot modify the calling i
  i = new int[]{9, 9};
}

```

The classic example of this difference in Java is a simple function to “swap” two arrays or Objects provided as arguments, which fails – one example with detailed discussion is here:

> **[Java is Pass by Value, Not Pass by Reference | DigitalOcean](https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference)**
>
> Technical tutorials, Q&A, events — This is an inclusive place where developers can find or lend support and discover new ways to contribute to the community.

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 7, 2020, 6:17am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/10 "2020-01-07T06:17:37Z")

</div>

Yes, I do understand.  
It seems to me that there are four distinct but related core issues that, when not explained _together_, contribute to and perpetuate the misunderstanding.

The first is a problem of semantics: ALL data items passed as arguments are “values” in that they are a copy of - the value - of the data items passed. The significance is in how that item is interpreted - i.e. what you can DO with that value. If it is a primitive, then it is merely a copy of - the value of - the original data item; and you can use the information contained in it, whereas if it is a pointer, then while it is still a copy of - the value of - the original data item - that original data item is a pointer to (“a means by which we gain direct access to”) another data object. So if we pass a pointer to a data item, we can reach _across_ and manipulate the item to which the pointer points (I resist the temptation to say “refers”.)  
So in fact, it doesn’t matter if the argument passed is a primitive or a pointer to a complex data item, then the original instance of that _argument_ cannot be changed by the called function/method - the only thing that can be changed is the actual data item that argument points to, IF that argument is a pointer.

The second is the “new” command. Java is inconsistent in that to create a primitive variable one has only to declare the type and the name of the new item:

```auto
int myInt;

```

but for a complex data item, we use the “new” command to actually allocate the space…:

```auto
myThing = new Thing;

```

and in this case “myThing” is a pointer, a handle by means of which the new Thing may be manipulated (not an Apple “Handle” from back in the day - that’s a pointer to a pointer).  
So if we say

```auto
Thing aThing;

```

we are creating only a _pointer to_ a complex data item - a means by which we might manipulate some real complex data item inf the future - NOT an actual item. Old C or assembly language programmers like me need to make sure we’re not tripped up by that!

Anyway, when we pass “myThing” we are passing a copy of - the value of - the variable “myThing”, which is only a pointer, which _refers to_ - gives us access to - the Thing data item we just created. If we pass “aThing”, then we are doing the same thing: passing only the the value of the pointer, except that in this case hasn’t been initialized to a real data item yet.

The third is our over-simplified English language. When we say “We can’t change what myThing points to”, or even “We can’t change the data item to which myThing points”, we are NOT necessarily saying “we can’t change _the actual item_ to which myThing happens to be pointing”. Grammatically those expressions are NOT the same at all, but the first two are dangerously and ambiguously similar to the third, and it is anybody’s guess which of those two critically different meanings the reader will internalize when those words are spoken. It’s a classic “who’s on first”.

The fourth: the syntactical elements which are glaringly absent from Java. You cannot say

```auto
&myPassedValue

```

in Java; it is simply not allowed. You cannot “back up” and fiddle with the original of the passed value; and you cannot/have no need to say

```auto
*myPassedValue

```

because if it’s a primitive then that construct makes no sense, and if it isn’t then Java already knows to treat it as a pointer and to dereference it.

THAT, to me, is the core of the issue, and to simply label the problem as “by reference vs by value” is to miss the point.

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 7, 2020, 8:22am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/11 "2020-01-07T08:22:51Z")

</div>

I think 90% of programming problems are communications problems. Here’s another example of the English language communication problem I mentioned above.  
“I want to change my car”. Does that mean “I want to modify the car I have - maybe paint it, or put stiffer suspension in it” or does it mean “I want to sell my car and buy another”?  
In the first instance I’m modifying some characteristic of the same car, while in the second I’m replacing the target of the token expression “my car” with an entirely different object. Our language doesn’t provide any formal grammatical way to disambiguate between those two interpretations, and we would rely on common usage to know what is meant.  
Context and custom figure heavily in speech: by way of example, and if you will please forgive the sexism, if a woman is heard to say “I want to change my husband”, it will likely be understood - for ugly historical and cultural reasons - to mean a different thing than if a man says “I want to change my wife”. Maybe “I want to change my hair” vs “I want to change my shirt” is a less provocative but equally valid example, and purposeful ambiguation might make for some passable humor. But what if my hair is in the form of a wig? Now what does “change” mean? What if I’m at my tailor, being fitted for a tux? What does “change the shirt” mean now? Alter? Replace?  
The comical ambiguities above might easily be resolved by saying “replace”, “modify” or “alter” instead of “change”, but in software it isn’t as easy, because culture doesn’t apply: saying “change what myPtr points to” in a discussion of language behavior could legitimately mean either, yet the difference is monumental, and central to the issue. Personally, in this context I think of “change” and “modify” as in the “hair” example above, and “replace” as in the “shirt” example, but that’s just me.  
In the discussions and arguments I’ve seen online, people seem to talk as if the terms are immutable, but they really aren’t, and I haven’t even begun to address the challenge experienced by people for whom English is not the primary language…  
So, to add my own “old C programmer” take on this “by value vs. by reference” thing, I think of a function argument as C’s “rvalue”: you cannot change an rvalue, only use the information contained in it. Yes, technically, you can do it locally within the function, of course, but that changes only the local copy, not the “real” data item. The data object _to which a pointer refers_, however, is an lvalue, and can be changed.  
A silly, illegal way of demonstrating the difference might be this:

```auto
myInt = new int(5); // yes, I know you can't do that.

```

then you could pass myInt as a pointer to the new int, and change the original somehow…

```auto
void myBumpFunc(int intPtr) {
  intPtr.int += 5;
}

```

you can’t do that, of course…  
but you CAN create a single element array of integers…

```auto
int[] myInt = new int[1];

```

“myInt” is a pointer to an array object containing a single integer, and we can pass it to a function to give access to the original:

```auto
void myBumpFunc(int[] iP) {
  iP[0] += 5;
}

```

but hey, who’d want to do that? 😉

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [January 7, 2020, 9:38am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/12 "2020-01-07T09:38:20Z")

</div>

IMO, most of this confusion arises b/c we’re taught to associate a variable to its data content as if they were the same thing.

When we declare a variable, we’re just reserving a tiny contiguous block of memory addresses (bytes), which in most languages they vary from 1 to 8 bytes.

The variable itself is merely a label for the 1st memory address of that memory block.

In Java, only the content of a variable’s memory block can be passed around to other variables or to function calls.

We can’t pass the memory address of the variable itself!

In some system languages like C, they have an `&` unary operator, which forces a variable spit out its memory address instead of the value its memory address block stores.

So we need to mentally separate the variable from its content if we really wanna understand how things work internally.

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 9, 2020, 2:23am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/13 "2020-01-09T02:23:54Z")

</div>

I tried your code - both the single float and the multiple - but couldn’t get it to behave… synchronization, maybe? Seems I should set up a call/response mechanism to synchronize the start of a block of values?

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [January 9, 2020, 2:38am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/14 "2020-01-09T02:38:47Z")

</div>

> [@julianop](#):
>
> but couldn’t get it to behave… synchronization, maybe?

- You should post your own attempt.
- That sketch example relies on the combo **noLoop()** / **redraw()**.
- So it doesn’t need any synchronization at all.

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 9, 2020, 7:36am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/15 "2020-01-09T07:36:30Z")

</div>

I think you think I mean screen sync; what I mean is sync with the start of the data block. I see no mechanism to identify the beginning of the block. I’m probably missing something…

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [January 9, 2020, 8:04am UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/16 "2020-01-09T08:04:23Z")

</div>

> [@julianop](#):
>
> ; what I mean is sync with the start of the data block.

I don’t have the hardware. But I believe the Processing sketch should fully start 1st (go thru’ **setup()** till the end) before Arduino can start sending bytes to it.

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 9, 2020, 3:17pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/17 "2020-01-09T15:17:49Z")

</div>

Agreed, but I see no mechanism to force that. I’ll need to build your code in a call-response structure. As I said, I’m not very fluent with the “object.method(parameter/arg)” structure of Java, and the more dots there are the more difficult it is for me to decode. I can’t yet get my head around

```auto
FloatBuffer buf = ByteBuffer.wrap(bytes).asFloatBuffer();

```

or

```auto
  buf.get(floats).rewind();

```

for example; I’m accustomed to the “verb(parameter/arg)” of traditional procedural programming. More than one dot confuses me !!

---

<div class="post-metadata">

### Author: ![GoToLoop](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/gotoloop/32/86_2.png) [@GoToLoop](https://discourse.processing.org/u/GoToLoop)
#### Post date: [January 9, 2020, 6:09pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/18 "2020-01-09T18:09:03Z")

</div>

> [@julianop](#):
>
> , and the more dots there are the more difficult it is for me to decode.

> [@julianop](#):
>
> More than one dot confuses me !!

We use the dot `.` access operator right after a reference in order to access 1 of its members:

> **[. (dot) / Reference](https://processing.org/reference/dot.html)**
>
> Provides access to an object's methods and data. An object is one instance of a class and may contain both methods (object functions) and data (object variables and constants), as specified in the cla…

Therefore we need to know the available members we can access from a reference before we can use the dot `.` operator on it.

Let’s examine the expression ByteBuffer.wrap(bytes).asFloatBuffer() which is immediately assigned to declared field FloatBuffer buf.

ByteBuffer is a `class` reference:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/ByteBuffer.html](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/ByteBuffer.html)

B/c it is a `class`, and not an object derived from it (instance), we can only access `static` members from it via the dot `.` operator.

So we invoke its `public static` member method **wrap()** via the dot `.` operator:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/ByteBuffer.html#wrap(byte[])](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/ByteBuffer.html#wrap(byte%5B%5D))

According to that method’s doc, it says it returns a `new` ByteBuffer object.

So the 2nd dot `.` operator acts upon what is returned by method **wrap()**, which is an instance of ByteBuffer, allowing us to access its non-`static` members as well.

So now we invoke its instance method **asFloatBuffer()**:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/ByteBuffer.html#asFloatBuffer()](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/ByteBuffer.html#asFloatBuffer())

Which states it returns a `new` FloatBuffer object:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/FloatBuffer.html](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/FloatBuffer.html)

We stop chaining dot `.` operators; and that last returned reference (AKA memory address or pointer) is finally assigned to field _buf_ of datatype FloatBuffer:  
`FloatBuffer buf = ByteBuffer.wrap(bytes).asFloatBuffer();`

As you can see from its Java doc link above, FloatBuffer is an `abstract class` that lacks a formal `public` constructor.

Although we can also get an instance of it via its `static` methods like **allocate()** & **wrap()**:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/FloatBuffer.html#allocate(int)](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/FloatBuffer.html#allocate(int))  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/FloatBuffer.html#wrap(float[])](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/FloatBuffer.html#wrap(float%5B%5D))

However, its `static` method **wrap()** accepts a `float[]` array only.

But we really need to pass a `byte[]` array b/c method Serial::**readBytes()** doesn’t work w/ `float[]`:

> **[readBytes() / Libraries](https://processing.org/reference/libraries/serial/Serial_readBytes_.html)**
>
> Reads a group of bytes from the buffer or null if there are none available. The version with no parameters returns a byte array of all data in the buffer. This is not efficient, but is easy to …

That’s why we had to indirectly get an instance of it via method ByteBuffer::**asFloatBuffer()**.

Now let’s check the statement: `buf.get(floats).rewind();`

We use the dot `.` operator in order to invoke method FloatBuffer::**get()** over field _buf_, which stores the reference of a FloatBuffer object:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/FloatBuffer.html#get(float[])](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/FloatBuffer.html#get(float%5B%5D))

That method informs us that it returns a FloatBuffer as “This buffer”.

It means it’s not a `new` instance but the same object that had been used to invoke it.

That is, the very reference stored in our field _buf_.

Such methods are said to be chainable, b/c they `return` itself, allowing us to keep on accessing members of the same reference in sequence via multiple dot `.` usage.

So the 2nd dot `.` operator invokes method **rewind()** over the same _buf_:  
[Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/Buffer.html#rewind()](http://Docs.Oracle.com/en/java/javase/11/docs/api/java.base/java/nio/Buffer.html#rewind())

Notice though method **rewind()** comes from its superclass Buffer.

Obviously, we coulda split the expression in 2:

```auto
buf.get(floats);
buf.rewind();

```

---

<div class="post-metadata">

### Author: ![julianop](https://avatars.discourse-cdn.com/v4/letter/j/57b2e6/32.png) [@julianop](https://discourse.processing.org/u/julianop)
#### Post date: [January 13, 2020, 4:28pm UTC](https://discourse.processing.org/t/reading-byte-array-into-float-expanding-on-serialcallresponse-example/16880/19 "2020-01-13T16:28:06Z")

</div>

Thank you for that **excellent** explanation 🙂
