mirror of
				https://github.com/immich-app/immich.git
				synced 2025-11-03 19:17:11 -05:00 
			
		
		
		
	fix(web): timezone handling in search filter (#7384)
This commit is contained in:
		
							parent
							
								
									57758293e5
								
							
						
					
					
						commit
						6ec4c5874b
					
				@ -3,7 +3,7 @@
 | 
				
			|||||||
  import Icon from '$lib/components/elements/icon.svelte';
 | 
					  import Icon from '$lib/components/elements/icon.svelte';
 | 
				
			||||||
  import { ProjectionType } from '$lib/constants';
 | 
					  import { ProjectionType } from '$lib/constants';
 | 
				
			||||||
  import { getAssetFileUrl, getAssetThumbnailUrl, isSharedLink } from '$lib/utils';
 | 
					  import { getAssetFileUrl, getAssetThumbnailUrl, isSharedLink } from '$lib/utils';
 | 
				
			||||||
  import { timeToSeconds } from '$lib/utils/time-to-seconds';
 | 
					  import { timeToSeconds } from '$lib/utils/date-time';
 | 
				
			||||||
  import { AssetTypeEnum, ThumbnailFormat, type AssetResponseDto } from '@immich/sdk';
 | 
					  import { AssetTypeEnum, ThumbnailFormat, type AssetResponseDto } from '@immich/sdk';
 | 
				
			||||||
  import {
 | 
					  import {
 | 
				
			||||||
    mdiArchiveArrowDownOutline,
 | 
					    mdiArchiveArrowDownOutline,
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@
 | 
				
			|||||||
  import { createEventDispatcher, onMount } from 'svelte';
 | 
					  import { createEventDispatcher, onMount } from 'svelte';
 | 
				
			||||||
  import { fly } from 'svelte/transition';
 | 
					  import { fly } from 'svelte/transition';
 | 
				
			||||||
  import Combobox, { type ComboBoxOption } from '../combobox.svelte';
 | 
					  import Combobox, { type ComboBoxOption } from '../combobox.svelte';
 | 
				
			||||||
  import { DateTime } from 'luxon';
 | 
					  import { parseUtcDate } from '$lib/utils/date-time';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  enum MediaType {
 | 
					  enum MediaType {
 | 
				
			||||||
    All = 'all',
 | 
					    All = 'all',
 | 
				
			||||||
@ -231,6 +231,9 @@
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const parseOptionalDate = (dateString?: string) => (dateString ? parseUtcDate(dateString) : undefined);
 | 
				
			||||||
 | 
					  const toStartOfDayDate = (dateString: string) => parseUtcDate(dateString)?.startOf('day').toISODate() || undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const search = async () => {
 | 
					  const search = async () => {
 | 
				
			||||||
    let type: AssetTypeEnum | undefined = undefined;
 | 
					    let type: AssetTypeEnum | undefined = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -246,16 +249,11 @@
 | 
				
			|||||||
      city: filter.location.city?.value,
 | 
					      city: filter.location.city?.value,
 | 
				
			||||||
      make: filter.camera.make?.value,
 | 
					      make: filter.camera.make?.value,
 | 
				
			||||||
      model: filter.camera.model?.value,
 | 
					      model: filter.camera.model?.value,
 | 
				
			||||||
      takenAfter: filter.date.takenAfter
 | 
					      takenAfter: parseOptionalDate(filter.date.takenAfter)?.startOf('day').toISO() || undefined,
 | 
				
			||||||
        ? DateTime.fromFormat(filter.date.takenAfter, 'yyyy-MM-dd').toUTC().startOf('day').toString()
 | 
					      takenBefore: parseOptionalDate(filter.date.takenBefore)?.endOf('day').toISO() || undefined,
 | 
				
			||||||
        : undefined,
 | 
					      isArchived: filter.isArchive || undefined,
 | 
				
			||||||
      takenBefore: filter.date.takenBefore
 | 
					      isFavorite: filter.isFavorite || undefined,
 | 
				
			||||||
        ? DateTime.fromFormat(filter.date.takenBefore, 'yyyy-MM-dd').toUTC().endOf('day').toString()
 | 
					      isNotInAlbum: filter.isNotInAlbum || undefined,
 | 
				
			||||||
        : undefined,
 | 
					 | 
				
			||||||
      /* eslint-disable unicorn/prefer-logical-operator-over-ternary */
 | 
					 | 
				
			||||||
      isArchived: filter.isArchive ? filter.isArchive : undefined,
 | 
					 | 
				
			||||||
      isFavorite: filter.isFavorite ? filter.isFavorite : undefined,
 | 
					 | 
				
			||||||
      isNotInAlbum: filter.isNotInAlbum ? filter.isNotInAlbum : undefined,
 | 
					 | 
				
			||||||
      personIds: filter.people && filter.people.length > 0 ? filter.people.map((p) => p.id) : undefined,
 | 
					      personIds: filter.people && filter.people.length > 0 ? filter.people.map((p) => p.id) : undefined,
 | 
				
			||||||
      type,
 | 
					      type,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@ -295,12 +293,8 @@
 | 
				
			|||||||
          model: searchQuery.model ? { label: searchQuery.model, value: searchQuery.model } : undefined,
 | 
					          model: searchQuery.model ? { label: searchQuery.model, value: searchQuery.model } : undefined,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        date: {
 | 
					        date: {
 | 
				
			||||||
          takenAfter: searchQuery.takenAfter
 | 
					          takenAfter: searchQuery.takenAfter ? toStartOfDayDate(searchQuery.takenAfter) : undefined,
 | 
				
			||||||
            ? DateTime.fromISO(searchQuery.takenAfter).toUTC().toFormat('yyyy-MM-dd')
 | 
					          takenBefore: searchQuery.takenBefore ? toStartOfDayDate(searchQuery.takenBefore) : undefined,
 | 
				
			||||||
            : undefined,
 | 
					 | 
				
			||||||
          takenBefore: searchQuery.takenBefore
 | 
					 | 
				
			||||||
            ? DateTime.fromISO(searchQuery.takenBefore).toUTC().toFormat('yyyy-MM-dd')
 | 
					 | 
				
			||||||
            : undefined,
 | 
					 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        isArchive: searchQuery.isArchived,
 | 
					        isArchive: searchQuery.isArchived,
 | 
				
			||||||
        isFavorite: searchQuery.isFavorite,
 | 
					        isFavorite: searchQuery.isFavorite,
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import { timeToSeconds } from './time-to-seconds';
 | 
					import { timeToSeconds } from './date-time';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('converting time to seconds', () => {
 | 
					describe('converting time to seconds', () => {
 | 
				
			||||||
  it('parses hh:mm:ss correctly', () => {
 | 
					  it('parses hh:mm:ss correctly', () => {
 | 
				
			||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
import { Duration } from 'luxon';
 | 
					import { DateTime, Duration } from 'luxon';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Convert time like `01:02:03.456` to seconds.
 | 
					 * Convert time like `01:02:03.456` to seconds.
 | 
				
			||||||
@ -11,3 +11,7 @@ export function timeToSeconds(time: string) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  return Duration.fromObject({ hours, minutes, seconds }).as('seconds');
 | 
					  return Duration.fromObject({ hours, minutes, seconds }).as('seconds');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function parseUtcDate(date: string) {
 | 
				
			||||||
 | 
					  return DateTime.fromISO(date, { zone: 'UTC' }).toUTC();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -35,6 +35,7 @@
 | 
				
			|||||||
  import type { Viewport } from '$lib/stores/assets.store';
 | 
					  import type { Viewport } from '$lib/stores/assets.store';
 | 
				
			||||||
  import { locale } from '$lib/stores/preferences.store';
 | 
					  import { locale } from '$lib/stores/preferences.store';
 | 
				
			||||||
  import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
 | 
					  import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
 | 
				
			||||||
 | 
					  import { parseUtcDate } from '$lib/utils/date-time';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const MAX_ASSET_COUNT = 5000;
 | 
					  const MAX_ASSET_COUNT = 5000;
 | 
				
			||||||
  let { isViewing: showAssetViewer } = assetViewingStore;
 | 
					  let { isViewing: showAssetViewer } = assetViewingStore;
 | 
				
			||||||
@ -143,13 +144,16 @@
 | 
				
			|||||||
    isLoading = false;
 | 
					    isLoading = false;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function getHumanReadableDate(date: string) {
 | 
					  function getHumanReadableDate(dateString: string) {
 | 
				
			||||||
    const d = new Date(date);
 | 
					    const date = parseUtcDate(dateString).startOf('day');
 | 
				
			||||||
    return d.toLocaleDateString($locale, {
 | 
					    return date.toLocaleString(
 | 
				
			||||||
      year: 'numeric',
 | 
					      {
 | 
				
			||||||
      month: 'long',
 | 
					        year: 'numeric',
 | 
				
			||||||
      day: 'numeric',
 | 
					        month: 'long',
 | 
				
			||||||
    });
 | 
					        day: 'numeric',
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      { locale: $locale },
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function getHumanReadableSearchKey(key: keyof SearchTerms): string {
 | 
					  function getHumanReadableSearchKey(key: keyof SearchTerms): string {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user