How to build a calendar to borrow and lend objects

I want to build a Smart Contract that can let a user borrow items lended by another user. I've got some problems with the calendar design though. How can I create/design a calendar that checks if the item that a user is trying to borrow is not available in some specific dates?

Example: I want to borrow a bike from the 6th of this month for 30 days. The smart contract sees that the bike is free from the 6th for 50 days so I can borrow it.

How I though to handle this: convert time from seconds passed from 1970 to DD/MM/YYYY and then store the information in a mapping(uint16 => mapping(uint8 => uint8)).

So for example: I want to borrow an item from the 6th of november of 2023 for 4 days. The smart contract saves this date like so:

dates[2023][11][6]
dates[2023][11][7]
dates[2023][11][8]
dates[2023][11][9]

Let's say that somebody else wants the bike for two days starting from the 7th of November of 2023. The Smart Contract checks if the item is available but finds that the mapping is already populated in those dates so it won't let my request through.

What do you think about my way to handle this? Do you have a better approach?

Of course in this case the Smart contract must iterate from the starting date (so in this case the 7th of November) and it would have a complexity of O(2) because the numbers of days to iterate are two.

Hey @Allennick
my first advise is to use uint256 instead of uint16 or uint8

To do this, you can save the timestamp of the borrow and add to it the duraton of the borrow.

uint256 borrowEnd = block.timestamp + 30 days

In this way you only have to check the borrowEnd value when someone else try to borrow a bike during that period

Hi thanks for your answer.

What happens if I borrow the item from the 7th of November 2023 for 4 days and someone asks to borrow the item from the 2nd of November up until the 5th of November?
I would answer that this request is valid because I check the value of your "borrowEnd" variable against my "requestedBorrowEnd" value (the 5th of November).

The "borrowEnd" value is saved in a mapping? How can you handle preordered periods for an item with just this variable?
Should it be saved in a mapping like so:

//the first uint256 is the "borrowStart" whilst the second one is the "borrowEnd" variable
mapping(uint256 => uint256) occupiedSlots 

I don't know which is your aim/idea. You should provide more info about what you want to achieve, like how it should work, what people can do etc.

Also I don't get this

mapping(uint256 => uint256) occupiedSlots 

My idea is to let people borrow items from a lender.
People can preorder items in the future.
So a person X can preorder an item for Y days starting from XX/YY/ZZZZ up until XX'/YY'/ZZZZ'.
My smart contract must check if the item is available in those days.
If you need more information I can provide it to you.

occupiedSlots is a mapping that contains a startingDate and an endingDate. With just a variable as you suggested I can't understand how to check if the item will be available in the days I selected.

It is literally a calendar.

This calendar handles the availability of many items.

Ok so, imagine you have an id for each product.
I would do it in this way:

mapping(uint256 => BorrowInfo) borrowInfo //uint256 is the itemId

struct BorrowInfo {
  bool available
  uint256 startDate;
  uint256 endDate;
}

And when you need to check if that item can be borrowed:

 function borrowItem(uint256 itemId, uint256 start, uint256 end) external {
        require(borrowInfo[itemId].available)
        require(start <= end)
        if(start < borrowInfo[itemId].end)
            require(end < borrowInfo[itemId].start)
        ...
    }

Yes the idea is pretty much what you show to me in that code.
But the borrowed item must contain more information on its future availability.
In the case you just described to me let's say that there is the item with ID = X and I borrow it from this day for 4 days. So the struct would be = {available = false, startDate = today (in seconds passed from 1970 of course), endDate = today + 4 days} and that's great.

Now let's say that you, another user of my Dapp, login in the same day as me and want the same item that I've just borrowed. So you see that it will be available from four days starting from now, you decide to preorder it from borrowInfo[ID of the item][endDate + 1 day] for 1 day.

So to be more precise let's think about this with a table.

In this table you can see a row with the item availability and some columns that range from today's date up until 14/09/2022.
We have both visited my dApp today (09/09/2022) and we want to book the same item, you try to borrow the item today but the Smart Contract says (nope, you can't), so you see that the item is available at the 13th but you choose to preorder it from 15/09/2022 for 1 day.
So to do this I need a more complex struct than the one you proposed (that was great, I really thank you by the way).

I would need something like:

//The first uint256 is the itemId, the second one is the startDate
mapping(uint256 => mapping(uint256 => BorrowInfo)) 
struct BorrowInfo {
  status string //can be 'PREORDERED, AVAILABLE, NOT_AVAILABLE
  uint256 endDate
}

Yex exactly, as I said only you know what you need. I hope the code example will be useful :stuck_out_tongue_winking_eye:

I think I was enough descriptive about my problem to be honest. That code example is good but it doesn't fully fit the example I have explained.
Thanks anyway.