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

Is there a way to query journeys from a certain timepoint to a certain time point? #283

Closed
bognar-dev opened this issue Jan 24, 2023 · 9 comments
Labels
how-to how to solve a specific use case question

Comments

@bognar-dev
Copy link

bognar-dev commented Jan 24, 2023

Here is my request:

{
from_location: '8098096',
  from_time: '2023-01-24',
  to_time: '2023-01-25'
}

this is how I try to call it

const { journeys } = await hafas.journeys(location, '8000261', {
        results: 20,
    })

I just couldn't find an option to pass in for the two date times.
I am also aware that i would probably have to convert the Dates to Date objects.

Is it possible to get journey data from all connections between two stations?
If you have any other questions regarding this, please ask me.

@derhuerst
Copy link
Member

You can pass the start/from date+time as departure into the options object:

await HAFAS.journeys('8098096', '8000261', {
	results: 20,
	// make an ISO 8601 string
	departure: from_time + 'T00:00+01:00',
})

This effectively queries journeys by their earliest departure time. Alternatively, you can pass in the latest acceptable arrival time as opt.arrival, and HAFAS will "search backwards in time". Passing both opt.departure and opt.arrival is not possible, due to limitations in the HAFAS API – It's been a while since have checked wether these limitations still apply though.

I am also aware that i would probably have to convert the Dates to Date objects.

Currently, with hafas-client@6, you can pass anything that new Date(input) can handle, so (almost all) ISO 8601 strings, Date objects, millisecond UNIX timestamps.

@derhuerst
Copy link
Member

derhuerst commented Jan 24, 2023

Is it possible to get journey data from all connections between two stations?

What does "all" mean in your context?

It might sound obvious, but there is an almost infinite number of possible journeys between two stops. Even if you only keep those that departure after from_time (from your example) and arrive before to_time, there are usually dozens or hundreds of possible journeys.

When called via hafas.journeys(), HAFAS's routing engine tries to find those that, according to some weighting of several factors (e.g. travel time, nr of changes, amount of walking, potentially many more), "fit well" (or "fit best", not sure if HAFAS has pareto-optimal routing).

This leads me to the question: What do you actually want to do?

@bognar-dev
Copy link
Author

bognar-dev commented Jan 24, 2023

@derhuerst

Let's say we pass the opt:

transfers: 0 // Maximum nr of transfers.

That should mean HAFAS is searching for only direct trains, correct?

Then combine it with the constraint of a timeframe of

from_time : 26.01.2023T09:00
to_time :25.01.2023T17:00
That should be a timeframe of 8 hours and with like a direct train once an hour it should return 8 trains possible?

If there is not such an option,
Then maybe looping with variable times could be an option.

Thank you very much for your fast replies.

@derhuerst
Copy link
Member

What do you actually want to do?

Using the method you described, you can iterate over those direct trains between the stops that the routing algorithm deemed "good enough". You don't necessarily get all trains running between those stops.

@bognar-dev
Copy link
Author

What do you actually want to do?

I want to get the ICE's between let's say Düsseldorf and Hamburg for the next 8 hours, and then filter for the one with the cheapest price?

How do tell the api to just give me the ICE's for 8 hours departure time slot?

@derhuerst
Copy link
Member

As I elaborated, that won't necessarily (as in: there are no guarantees) give you all ICEs between the two stations, and thus not necessarily give you the cheapest. For pricing, there is a different API (flavour) used by db-prices.

Nevertheless, here's a snippet with the aforementioned limitations:

import {createClient} from 'hafas-client/index.js'
import {profile as dbProfile} from 'hafas-client/p/db/index.js'

// don't send `rtMode: REALTIME`, breaks iteration
// see https://github.com/public-transport/hafas-client/issues/282#issuecomment-1373612431
const dbProfileWithoutRtModeRealtime = {
	...dbProfile,
	transformReqBody: (ctx, body) => {
		const reqBody = dbProfile.transformReqBody(ctx, body)
		delete reqBody.svcReqL[0].cfg.rtMode
		return reqBody
	}
}

const hafas = createClient(dbProfileWithoutRtModeRealtime, 'journeys iteration demo')

const from = '8000085' // Düsseldorf Hbf
const to = '8096009' // HAMBURG
const start = Date.parse('2023-02-14T07:00+01:00')

const latestJourneyDep = (journeys) => {
	const deps = journeys.map((journey) => {
		const dep = journey.legs[0].departure || j.legs[0].plannedDeparture
		return +Date.parse(dep)
	})
	deps.sort()
	return deps[0]
}

const collectedJourneys = []
let journeysOpts = {departure: start}
while (true) {
	const {
		journeys,
		laterRef,
	} = await hafas.journeys(from, to, journeysOpts)

	if (journeys.length === 0) break
	collectedJourneys.push(...journeys)
	if ((latestJourneyDep(journeys) - start) > 8 * 3600 * 1000) break

	journeysOpts = {laterThan: laterRef}
}

console.log(collectedJourneys)

Due to #282 (comment), currently, the default DB profile does not allow iterating ("scrolling") through journeys() results using opt.laterThan, so we patch transformReqBody() not to send rtMode: 'REALTIME'.

@derhuerst
Copy link
Member

Does that answer your question?

@bognar-dev
Copy link
Author

Yes thank you very much for the effort

@derhuerst derhuerst added the how-to how to solve a specific use case label Feb 10, 2023
@traines-source
Copy link
Contributor

traines-source commented May 23, 2023

How do tell the api to just give me the ICE's for 8 hours departure time slot?

Just as a side note, I think for the use case of direct connections it is much easier to query the departure board for the origin station and the arrival board for the destination station and join the trips on your own (easy since they will have the same tripId). For the departure/arrival boards, you can specify a duration and/or maxResults. You don't get pricing information then though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
how-to how to solve a specific use case question
Development

No branches or pull requests

3 participants