Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Datetime #118

Merged
merged 2 commits into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions PROGRESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ List grouped by domains and categorized based on their similar behaviors
### Date

- [ ] date
- [ ] datetime
- [ ] input_datetime
- [x] datetime
- [x] input_datetime
- [ ] parse date in state
- [ ] time
- [ ] time input like `timer`
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ For "Operating System" or "Supervised" installation methods, you can install ha-

1. **Add Repository**: To begin, add the ha-fusion add-on repository to your Home Assistant instance. Click the button below or manually add the repository using this URL: <https://github.com/matt8707/addon-ha-fusion>.

[![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fmatt8707%2Faddon-ha-fusion)
[![Open your Home Assistant instance and show the add add-on repository dialog with a specific repository URL pre-filled.](https://my.home-assistant.io/badges/supervisor_add_addon_repository.svg)](https://my.home-assistant.io/redirect/supervisor_add_addon_repository/?repository_url=https%3A%2F%2Fgithub.com%2Fmatt8707%2Faddon-ha-fusion)

2. **Install Add-on**: After adding the repository, refresh the add-on store page. Locate ha-fusion in the list and proceed with the installation.

Expand All @@ -37,12 +37,12 @@ If you're using the "Container" or "Core" installation methods, ha-fusion can be
1. **Docker Compose File**: Place your edited copy of the [docker-compose.yml](https://github.com/matt8707/ha-fusion/blob/main/docker-compose.yml) file in a suitable directory.

2. **Create Container**:
Run the following commands in your terminal to start the container:
Run the following commands in your terminal to start the container:

```bash
cd path/to/docker-compose.yml
docker-compose up -d ha-fusion
```
```bash
cd path/to/docker-compose.yml
docker-compose up -d ha-fusion
```

#### Update

Expand Down
5 changes: 5 additions & 0 deletions src/lib/Main/Button.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@
openModal(() => import('$lib/Modal/InputNumberModal.svelte'), { sel });
break;

case 'datetime':
case 'input_datetime':
openModal(() => import('$lib/Modal/InputDateModal.svelte'), { sel });
break;

case 'input_select':
case 'select':
openModal(() => import('$lib/Modal/InputSelectModal.svelte'), { sel });
Expand Down
3 changes: 2 additions & 1 deletion src/lib/Main/Camera.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@
title={$lang('camera')}
style:width="{width}px"
style:aspect-ratio="{width} / {height}"
style:transform="scale({Math.min(offsetHeight / height, offsetWidth / width)}) translate(-50%, -50%)"
style:transform="scale({Math.min(offsetHeight / height, offsetWidth / width)}) translate(-50%,
-50%)"
/>
{/if}
</div>
Expand Down
120 changes: 120 additions & 0 deletions src/lib/Modal/InputDateModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<script lang="ts">
import { states, lang, connection, motion, selectedLanguage } from '$lib/Stores';
import Modal from '$lib/Modal/Index.svelte';
import ConfigButtons from '$lib/Modal/ConfigButtons.svelte';
import { getDomain, getName, relativeTime } from '$lib/Utils';
import { callService } from 'home-assistant-js-websocket';

export let isOpen: boolean;
export let sel: any;

$: entity = $states[sel?.entity_id];
$: state = entity?.state;
$: type = getType(entity?.attributes?.has_date, entity?.attributes?.has_time);
$: domain = getDomain(entity.entity_id) as string;

/**
* Handles input_datetime
*/
function handleChange(event: any) {
if (!entity?.entity_id) return;

const target = event?.target as HTMLInputElement;

const service = domain === 'datetime' ? 'set_value' : 'set_datetime';
const data =
domain === 'datetime' ? { datetime: target?.value } : type && { [type]: target?.value };

callService($connection, domain, service, {
entity_id: entity?.entity_id,
...data
});
}

/**
* datetime | date | time | timestamp
*/
function getType(date: boolean, time: boolean) {
if (date && time) return 'datetime';
else if (date) return 'date';
else if (time) return 'time';
}

function format(state: any, type: string) {
try {
if (type === 'datetime') {
return new Intl.DateTimeFormat($selectedLanguage, {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
}).format(new Date(state));
} else if (type === 'date') {
return new Intl.DateTimeFormat($selectedLanguage, {
year: 'numeric',
month: 'long',
day: 'numeric'
}).format(new Date(state));
} else if (type === 'time') {
// 'HH:MM:SS'
const timeParts = state.split(':');
const date = new Date();
date.setHours(timeParts[0], timeParts[1], timeParts[2] || 0);
return new Intl.DateTimeFormat($selectedLanguage, {
hour: 'numeric',
minute: '2-digit',
second: '2-digit',
hour12: undefined
}).format(date);
}
} catch (error) {
console.error('Error formatting date/time:', error);
return 'Invalid Date/Time';
}
}

function convert(state: string) {
const date = new Date(state);
const year = date.getUTCFullYear();
const month = (date.getUTCMonth() + 1).toString().padStart(2, '0');
const day = date.getUTCDate().toString().padStart(2, '0');
const hours = date.getUTCHours().toString().padStart(2, '0');
const minutes = date.getUTCMinutes().toString().padStart(2, '0');
const formattedDateTime = `${year}-${month}-${day}T${hours}:${minutes}`;
return formattedDateTime;
}
</script>

{#if isOpen}
<Modal>
<h1 slot="title">{getName(sel, entity)}</h1>

<h2>
{#if domain === 'datetime' || type === 'datetime'}
{$lang('date_or_time')}
{:else if type}
{$lang(type)}
{/if}

<span class="align-right">
{format(state, type || 'datetime')}
</span>
</h2>

<input
class="input"
type={domain === 'datetime' || type === 'datetime' ? 'datetime-local' : type}
value={domain === 'datetime' ? convert(state) : state}
on:change={handleChange}
/>

<ConfigButtons />
</Modal>
{/if}

<style>
.input[type='datetime-local'] {
color-scheme: dark;
}
</style>