more updates to handle date ranges with my custom range language
This commit is contained in:
@@ -155,7 +155,7 @@ export class DatePickerComponent implements ControlValueAccessor {
|
||||
const hours = x.hours ? "-"+x.hours + "H" : "";
|
||||
const minutes = x.minutes ? "-"+x.minutes + "m" : "";
|
||||
|
||||
const timeRange = `B${years}${months}${days}${hours}${minutes}/Bm`;
|
||||
const timeRange = `B${years}${months}${days}${hours}${minutes}/Bm`;
|
||||
|
||||
const newValue = new DateValue("RELATIVE", timeRange, timeRange);
|
||||
this.setDateValue(newValue);
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Overlay } from "@angular/cdk/overlay";
|
||||
|
||||
import { DateTime, Duration } from "luxon";
|
||||
import { DateValue } from '../components/datepicker/date-picker.component';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'pdb-plot-view',
|
||||
@@ -190,11 +191,11 @@ export class PlotViewComponent {
|
||||
}
|
||||
|
||||
zoomRange(range: SelectionRange) {
|
||||
this.shiftDate(this.config?.dateRange.value!, range.startPercentOfDateRange, range.endPercentOfDateRange-1);
|
||||
this.shiftDate(this.config?.dateRange!, range.startPercentOfDateRange, range.endPercentOfDateRange-1);
|
||||
}
|
||||
|
||||
zoomWithDateAnchor(dateAnchor: DateAnchor){
|
||||
this.shiftDateByAnchor(this.config?.dateRange.value!, dateAnchor.cursorPercentOfDateRange, dateAnchor.zoomFactor);
|
||||
this.shiftDateByAnchor(this.config?.dateRange!, dateAnchor.cursorPercentOfDateRange, dateAnchor.zoomFactor);
|
||||
}
|
||||
|
||||
zoomByScroll(event: WheelEvent) {
|
||||
@@ -295,18 +296,27 @@ export class PlotViewComponent {
|
||||
* shiftDateByAnchor(dateRangeAsString, 0.20, 0.5) zooms in by 50%, so that the date that was at 20% before the zoom is still at 20% after the zoom
|
||||
* shiftDateByAnchor(dateRangeAsString, 0.33, 2) zooms out by 50%, so that the date that was at 33% before the zoom is still at 33% after the zoom
|
||||
*/
|
||||
shiftDateByAnchor(dateRange:string, anchorInPercentOfDateRange:number, zoomFactor:number)
|
||||
shiftDateByAnchor(dateValue:DateValue, anchorInPercentOfDateRange:number, zoomFactor:number)
|
||||
{
|
||||
const dateRangeParsed = this.parseDateRange(dateRange);
|
||||
const dateRangeInSeconds = Math.floor(dateRangeParsed.duration.toMillis()/1000);
|
||||
debugger;
|
||||
const dateRangeParsed = this.parseDateRange(dateValue);
|
||||
dateRangeParsed.subscribe({
|
||||
next: (dataRange: DateRange) => {
|
||||
const dateRangeInSeconds = Math.floor(dataRange.duration.toMillis()/1000);
|
||||
|
||||
const anchorTimestampInSeconds = dateRangeParsed.startDate.plus(Math.floor(dateRangeInSeconds*anchorInPercentOfDateRange)*1000);
|
||||
const newDateRangeInSeconds = dateRangeInSeconds * zoomFactor;
|
||||
const anchorTimestampInSeconds = dataRange.startDate.plus(Math.floor(dateRangeInSeconds*anchorInPercentOfDateRange)*1000);
|
||||
const newDateRangeInSeconds = dateRangeInSeconds * zoomFactor;
|
||||
|
||||
const newStartDate = anchorTimestampInSeconds.minus(newDateRangeInSeconds*anchorInPercentOfDateRange*1000);
|
||||
const newEndDate = newStartDate.plus({seconds: newDateRangeInSeconds});;
|
||||
|
||||
this.setDateRange(newStartDate, newEndDate);
|
||||
},
|
||||
error: (err: any) => {
|
||||
window.console.error("failed to parse DateValue into DateRange: ", err);
|
||||
}
|
||||
})
|
||||
|
||||
const newStartDate = anchorTimestampInSeconds.minus(newDateRangeInSeconds*anchorInPercentOfDateRange*1000);
|
||||
const newEndDate = newStartDate.plus({seconds: newDateRangeInSeconds});;
|
||||
|
||||
this.setDateRange(newStartDate, newEndDate);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,27 +328,36 @@ export class PlotViewComponent {
|
||||
* shiftDate(dateRangeAsString, -0.5, -0.5) will move the range by half its size to older values
|
||||
* shiftDate(dateRangeAsString, 1, 1) will move the range by its size to newer values
|
||||
*/
|
||||
shiftDate(dateRange: string, factorStartDate: number, factorEndDate: number)
|
||||
shiftDate(dateValue: DateValue, factorStartDate: number, factorEndDate: number)
|
||||
{
|
||||
const dateRangeParsed = this.parseDateRange(dateRange);
|
||||
const dateRangeInSeconds = Math.floor(dateRangeParsed.duration.toMillis()/1000);
|
||||
|
||||
const newStartDate = dateRangeParsed.startDate.plus({seconds: dateRangeInSeconds*factorStartDate});
|
||||
const newEndDate = dateRangeParsed.endDate.plus({seconds: dateRangeInSeconds*factorEndDate});
|
||||
|
||||
this.setDateRange(newStartDate, newEndDate);
|
||||
debugger;
|
||||
this.parseDateRange(dateValue).subscribe(
|
||||
dateRangeParsed => {
|
||||
const dateRangeInSeconds = Math.floor(dateRangeParsed.duration.toMillis()/1000);
|
||||
|
||||
const newStartDate = dateRangeParsed.startDate.plus({seconds: dateRangeInSeconds*factorStartDate});
|
||||
const newEndDate = dateRangeParsed.endDate.plus({seconds: dateRangeInSeconds*factorEndDate});
|
||||
|
||||
this.setDateRange(newStartDate, newEndDate);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
parseDateRange(dateRangeAsString : string) : DateRange {
|
||||
const startDate = DateTime.fromFormat(dateRangeAsString.slice(0, 19), this.DATE_PATTERN );
|
||||
const endDate = DateTime.fromFormat(dateRangeAsString.slice(22, 41), this.DATE_PATTERN );
|
||||
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
duration: endDate.diff(startDate),
|
||||
};
|
||||
parseDateRange(dateValue : DateValue) : Observable<DateRange> {
|
||||
return this.service.toDateRange(dateValue);
|
||||
/*
|
||||
.pipe(map((dateRangeAsString:string) => {
|
||||
const startDate = DateTime.fromFormat(dateRangeAsString.slice(0, 19), this.DATE_PATTERN );
|
||||
const endDate = DateTime.fromFormat(dateRangeAsString.slice(22, 41), this.DATE_PATTERN );
|
||||
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
duration: endDate.diff(startDate),
|
||||
};
|
||||
}));
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -3,11 +3,16 @@ import { HttpClient, HttpParams } from "@angular/common/http";
|
||||
import { Observable } from "rxjs";
|
||||
import { map } from "rxjs/operators";
|
||||
import { DateValue } from "./components/datepicker/date-picker.component";
|
||||
import { DateRange } from "./plot-view/plot-view.component";
|
||||
import { DateTime } from "luxon";
|
||||
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class PlotService {
|
||||
|
||||
readonly DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
|
||||
|
||||
plotTypes: Array<PlotType>;
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
@@ -253,6 +258,20 @@ export class PlotService {
|
||||
),
|
||||
);
|
||||
}
|
||||
toDateRange(dateValue: DateValue): Observable<DateRange> {
|
||||
return this.http.post<{start: string, end:string, startEpochMilli: number, endEpochMilli: number}>("//" + window.location.hostname+":" + window.location.port +"/api/dates",dateValue)
|
||||
.pipe(map((data) => {
|
||||
const startDate = DateTime.fromFormat(data.start.slice(0, -1), this.DATE_PATTERN );
|
||||
const endDate = DateTime.fromFormat(data.end.slice(0, -1), this.DATE_PATTERN );
|
||||
|
||||
|
||||
return {
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
duration: endDate.diff(startDate),
|
||||
};
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
export class PlotType {
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
package org.lucares.pdb.plot.api;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.lucares.pdb.api.DateTimeRange;
|
||||
import org.lucares.utils.Preconditions;
|
||||
|
||||
public class DateTimeRangeParser {
|
||||
|
||||
private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public static DateTimeRange parse(final OffsetDateTime offsetTime, final String datePeriod) {
|
||||
|
||||
final String[] startEnd = datePeriod.split(Pattern.quote("/"));
|
||||
@@ -122,4 +128,16 @@ public class DateTimeRangeParser {
|
||||
throw new IllegalArgumentException("invalid input: " + timeDefinition);
|
||||
}
|
||||
|
||||
public static DateTimeRange parseAbsolute(final String dateRangeAsString) {
|
||||
final String[] startEnd = dateRangeAsString.split(Pattern.quote(" - "));
|
||||
Preconditions.checkEqual(startEnd.length, 2, "invalid date range: ''{0}''", dateRangeAsString);
|
||||
|
||||
final String startString = startEnd[0];
|
||||
final String endString = startEnd[1];
|
||||
|
||||
final OffsetDateTime start = LocalDateTime.parse(startString, DATE_FORMAT).atOffset(ZoneOffset.UTC);
|
||||
final OffsetDateTime end = LocalDateTime.parse(endString, DATE_FORMAT).atOffset(ZoneOffset.UTC);
|
||||
|
||||
return new DateTimeRange(start, end);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
package org.lucares.pdb.plot.api;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.lucares.pdb.api.DateTimeRange;
|
||||
import org.lucares.recommind.logs.GnuplotAxis;
|
||||
import org.lucares.recommind.logs.GnuplotSettings;
|
||||
import org.lucares.utils.Preconditions;
|
||||
|
||||
public class PlotSettings {
|
||||
|
||||
@@ -96,12 +92,7 @@ public class PlotSettings {
|
||||
final DateTimeRange dateTimeRange = DateTimeRangeParser.parse(OffsetDateTime.now(), dateValue.getValue());
|
||||
return dateTimeRange;
|
||||
case ABSOLUTE:
|
||||
final String[] startEnd = dateValue.getValue().split(Pattern.quote(" - "));
|
||||
Preconditions.checkEqual(startEnd.length, 2, "invalid date range: ''{0}''", dateValue);
|
||||
|
||||
final OffsetDateTime startDate = LocalDateTime.parse(startEnd[0], DATE_FORMAT).atOffset(ZoneOffset.UTC);
|
||||
final OffsetDateTime endDate = LocalDateTime.parse(startEnd[1], DATE_FORMAT).atOffset(ZoneOffset.UTC);
|
||||
return new DateTimeRange(startDate, endDate);
|
||||
return DateTimeRangeParser.parseAbsolute(dateValue.getValue());
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ package org.lucares.pdbui;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.text.Collator;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -26,6 +28,9 @@ import org.lucares.pdb.api.DateTimeRange;
|
||||
import org.lucares.pdb.api.QueryWithCaretMarker;
|
||||
import org.lucares.pdb.api.QueryWithCaretMarker.ResultMode;
|
||||
import org.lucares.pdb.datastore.Proposal;
|
||||
import org.lucares.pdb.plot.api.DateTimeRangeParser;
|
||||
import org.lucares.pdb.plot.api.DateValue;
|
||||
import org.lucares.pdb.plot.api.DateValue.DateType;
|
||||
import org.lucares.pdb.plot.api.PlotSettings;
|
||||
import org.lucares.pdbui.domain.AutocompleteProposal;
|
||||
import org.lucares.pdbui.domain.AutocompleteProposalByValue;
|
||||
@@ -345,6 +350,22 @@ public class PdbController implements HardcodedValues, PropertyKeys {
|
||||
return result;
|
||||
}
|
||||
|
||||
@RequestMapping(path = "/dates", //
|
||||
method = RequestMethod.POST, //
|
||||
consumes = MediaType.APPLICATION_JSON_VALUE, //
|
||||
produces = MediaType.APPLICATION_JSON_VALUE //
|
||||
)
|
||||
@ResponseBody
|
||||
public DateTimeRange dates(@RequestBody final DateValue dateValue) {
|
||||
final DateType type = dateValue.getType();
|
||||
final DateTimeRange result = switch (type) {
|
||||
case RELATIVE -> DateTimeRangeParser.parse(OffsetDateTime.now(ZoneId.of("UTC")), dateValue.getValue());
|
||||
case QUICK -> DateTimeRangeParser.parse(OffsetDateTime.now(ZoneId.of("UTC")), dateValue.getValue());
|
||||
case ABSOLUTE -> DateTimeRangeParser.parseAbsolute(dateValue.getValue());
|
||||
};
|
||||
return result;
|
||||
}
|
||||
|
||||
@PostMapping(path = "/data", consumes = MediaType.MULTIPART_MIXED_VALUE)
|
||||
@ResponseBody
|
||||
@ResponseStatus(code = HttpStatus.CREATED)
|
||||
|
||||
Reference in New Issue
Block a user