I'm making use of open trip planner using the jython scripting method explained here: http://docs.opentripplanner.org/en/latest/Scripting/
(specifically 'Using OTP as a library') and am using a script very similar to their example script
For testing purposes I have two csv files containing 40 locations each. The locations are inside the Netherlands and I have loaded both the dutch gtfs and map. The strange thing is that the code that calculates the public transport trip times (line 32 in the example script: res = spt.eval(colleges), using modes WALK,TRANSIT) takes longer when I specify a day other than today.
An example:
req.setDateTime(2018, 12, 8, 16, 00, 00) # today
spt.eval(my_data) # -> takes ~7 - 10 seconds
req.setDateTime(2018, 12, 7, 16, 00, 00) # yesterday
spt.eval(my_data) # -> takes ~30 - 40 seconds
When not setting req.setDateTime(), spt.eval() is even faster. Note that I ran the script on the 6th, for the 6th, as well, and it was fast then too, so it's certainly related to "today" and not specifically the 8th.
Of course my primary question is, how do I make it fast for days other than today? (my main interest is actually tomorrow)
Is it related to when the OTP instance is started or is it some internal optimization? I don't think it's related to the building of the graph because that was built a couple of days ago. I was looking into providing a day or datetime setting when initializing OTP but am unable to find that in the docs.
(I haven't tried messing with my system time yet, but that's also an option I'm not very fond of). Any ideas or comments are welcome. If necessary I will provide a reproducible sample tomorrow.
This problem was actually caused because of how I used req.setDateTime() in combination with req.setMaxTimeSec().
Basically, setMaxTimeSec() uses the date set by setDateTime() as a starting point, and defines a worstTime (aka the last possible time) to that date time + the maxTimeSec. However, if setDateTime() was not yet set when calling setMaxTimeSec(), the current date time is used instead. This will consequently cause problems when you happen to call setDateTime() AFTERWARDS. Example:
setMaxTimeSec(60*60) # Sets worst time to now + 1 hour
setDateTime(yesterday) # Sets departure time to yesterday
This example has a very long time window to search for solutions! Instead of only looking within an hour time, we are now looking in a window of 25 hours!
Anyway, a simple solution is to first call setDateTime(), and then setMaxTimeSec():
setDateTime(yesterday) # Sets departure time to yesterday
setMaxTimeSec(60*60) # Sets worst time to yesterday + 1 hour
Alternatively, if, for some reason, you can't switch these methods, you can always correct the setMaxTimeSec() with the time difference between now and your setDateTime()-value:
date = datetime.strptime('2019-01-08 21:00', '%Y-%m-%d %H:%M')
date_seconds = time.mktime(date.timetuple())
now_seconds = time.mktime(datetime.now().timetuple())
date_diff_seconds = int(round(date_seconds - now_seconds))
req.setMaxTimeSec(60*60 + date_diff_seconds)
req.setDateTime(date.year, date.month, date.day, date.hour, date.minute, 00)
Related
I want to get the runtime of an active task. In the REST API page of /applications/[app-id]/stages/[stage-id], I can get tasks info in detail.
enter image description here
You can see, the executorRunTime is 0 when a task is not completed. I think I can get the runTime according to launchTime. Suppose the launchTime is 2017-12-21T03:15:31.106GMT. I use the following code to compute the runTime.
val format = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'.'sss'GMT'", Locale.ENGLISH)
format.setTimeZone(TimeZone.getTimeZone("GMT"))
val launchTime = format.parse("2017-12-21T03:15:31.106GMT").getTime
val runTime = Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTimeInMillis -
launchTime
But I get a negative number. Is the time format wrong? Or what?
TL;DR
String launchTimeString = "2017-12-21T03:15:31.106GMT";
launchTimeString = launchTimeString.replaceFirst("GMT$", "Z");
long launchTime = Instant.parse(launchTimeString).toEpochMilli();
long runTime = System.currentTimeMillis() - launchTime;
(Sorry, I can write only Java 8 code, I will have to trust you to translate.)
java.time and ISO 8601
The date and time classes from Java 1.0 and 1.1 are long outdated, and SimpleDateFormat in particular notoriously troublesome. I recommend you stop using them and use java.time, the modern Java date and time API instead. It is so much nicer to work with.
Your launch time string is a bit funny. It resembles the ISO 8601 standard format with the characteristic T between the date and the time, but has a non-standard GMT in the end, where strings following the standard would usually have Z (or a positive or negative offset from UTC). Since the modern date and time classes parse ISO 8601 as their default, that is, without any explicit formatter, and since writing format pattern strings seems to be an endless source of bugs (it certainly isn’t just you), I found it tempting to modify your string to fit the standard and then parse it.
What was wrong in your format pattern?
There are two bugs in you format pattern string:
You want uppercase HH for hour of day. Lowercase hh is for hour within AM or PM, in the interval 1 through 12. With SimpleDateFormat this bug usually “just” means that an hour of 12 is understood as 00 (which would have given you a very long run time) (the modern DateTimeFormatter more eagerly tells you you have a bug if you try the same with that class).
While lowercase ss is correct for seconds, milliseconds are uppercase SSS. This must have been what hit you: 106 in you string was taken to be seconds rather than milliseconds, so if running your code before 03:16:46, you got a negative run time.
So both bugs boil down to: Format pattern strings are case sensitive, so you need to beware the correct case.
Links
Oracle tutorial: Date Time, explaining how to use java.time.
Wikipedia article on ISO 8601.
I have been trying to find a nice way to format a timestamp of the current date & time with milliseconds using Python 3's native time library.
However there's no directive for milliseconds in the standard documentation https://docs.python.org/3/library/time.html#time.strftime.
There's undocumented directives though, like %s which will give the unix timestamp. Is there any other directives like this?
Code example:
>>> import time
>>> time.strftime('%Y-%m-%d %H:%M:%S %s')
'2017-08-28 09:27:04 1503912424'
Ideally I would just want to change the trailing %s to some directive for milliseconds.
I'm using Python 3.x.
I'm fully aware that it's quite simple to get milliseconds using the native datetime library, however I'm looking for a solution using the native time library solely.
If you insist on using time only:
miliSeconds = time.time()%1*1000
time() returns accurately the time since the epoch. Since you already have the the date up to a second, you don't really care this is a time delta, since the remaining fraction is what you need to add anyway to what you have already to get the accurate date. %1 retrieves the fraction and then I convert the numbers to millisecond by multiplying by 1000.
note
Note that even though the time is always returned as a floating point
number, not all systems provide time with a better precision than 1
second. While this function normally returns non-decreasing values, it
can return a lower value than a previous call if the system clock has
been set back between the two calls.
Taken from https://docs.python.org/3/library/time.html#time.time. But this means there is no way to do what you want. You may be able to do something more robust with process_time, but that would have to be elaborate.
I am working on a Visual C++ project, and I need to get duration of movie from a chosen file. I use Mediainfo.dll to retrieve this information (movieFile->General->DurationString;). The problem is when duration is more then one hour, I don't get seconds, i.e. seconds are always displayed as 00. When duration is less then one hour, everything is fine. I had also tried with movieFile->General->DurationMillis;, which returns duration in miliseconds, but I also get 00 seconds. Does anyone knows what might be the problem?
I don't know which intermediate layer you use, but from MediaInfo, MediaInfo::Get(Stream_General, 0, "Duration") returns a value in milliseconds for sure.
MediaInfo::Get(Stream_General, 0, "Duration/String3") will return duration in "HH:MM:SS.mmm" format.
Jérôme, developer of MediaInfo
I have a situation where the relative time is more important to a user than an absolute time. So it's more important to be able to quickly say "event happened 5 days and 5 hours ago" than "event happened at 1 PM CDT and it's 5 PM CST 5 days later now."
We store our dates in UTC and convert to display for the user:
pDateTime = DateTime.SpecifyKind(pDateTime, DateTimeKind.Utc);
DateTimeZone dateTimeZone = DateTimeZoneProviders.Tzdb[pCurrentUser.PreferredTimezone];
return Instant.FromDateTimeUtc(pDateTime).InZone(dateTimeZone).ToString("HH':'mm':'ss' 'MM'/'dd'/'yy' 'x", CultureInfo.InvariantCulture);
We'll be using NodaTime 1.2 when it's fully out and just used vanilla ToString before.
However, times using this pattern end up using the daylight status of the time as opposed to the current daylight status. This means that times look something like: 16:15:32 10/25/13 CDT even though we have now transitioned to CST.
It is an absolute measure of the time. This forces the user to do the logic: "How long ago was that? Is it daylight saving time now? If so, the difference is x. If not, I have to add or subtract an hour? That makes the difference y."
Meanwhile, a relative measure of the time would display 15:15:32 10/25/13 CST in the absence of DST. This forces the user to do no conversions and allows them to compute what that time means in context much easier.
In a display that has numerous dates, it can get tricky to do the absolute time logic over the entire set. Doing it once is tricky to get right. However, a friendly relative string like "posted 5 hours ago" also forces them to resolve both the date and time themselves - that information is still important.
A compromise might be to do the posted blank hours/minutes ago for the first 24 hours or to include both the friendly string and absolute time - these are both patterns I've seen done.
But ignoring those, is there a way in NodaTime to imbue a time with a specific daylight status in order to get times displaying in a relative context?
However, times using this pattern end up using the daylight status of the time as opposed to the current daylight status. This means that times look something like: 16:15:32 10/25/13 CDT even though we have now transitioned to CST.
Yes, and it should. Displaying a date/time with CST despite that date/time occurring in CDT would be very odd, IMO.
So it's more important to be able to quickly say "event happened 5 days and 5 hours ago" than "event happened at 1 PM CDT and it's 5 PM CST 5 days later now."
In that case you shouldn't be displaying a date/time at all, in my view. Convert both ZonedDateTime values to Instant, take the Duration between them, and then you can see that it's 5 days and 5 hours ago. (I can't remember how much help we provide with that - you may need to manually take the number of ticks and divide by NodaConstants.TicksPerStandardDay etc. Look at DurationPattern to see if it helps though.)
Alternatively, if you really want to display a date and time, but still easily be able to extract the difference between them mentally, two options suggest themselves:
Use OffsetDateTime instead; there you could force the offsets to be the same, although I still think it would be odd to display an offset which wasn't actually the current offset in the zone you were observing the time in. Or you could just display the relevant offset at the time, so -5 for CST and -4 for CDT.
Just display everything in UTC, so that daylight saving transitions are irrelevant.
Note that you can't get months between the two ZonedDateTime values, as we're dealing with an elapsed time (a duration) rather than calendar-logical arithmetic (a period).
I am hoping to get a quick answer to one question about NodaTime before downloading it. So far, I am reading about NodaTime and its API and it seems very carefully thought out.
I hope it might help eliminate some of the chaos I've been encountering in an application that has a database back-end, a desktop client with a database provider, and a web client that must run on the major browsers. The support for ISO 8601 on DateTime and Time varies greatly on the various database, database provider, and web platforms. Internet Explorer, for example, follows ISO 8601 but SQL Server does not; web UI timepickers do not because Chrome does not.
QUESTION: In NodaTime, is 24:00 a valid Time value? Is 24 a valid argument for the hours parameter of its Time constructors?
BACKGROUND: ISO 8601 allows for two representations of midnight: 00:00 for "midnight this morning" and 24:00 for "midnight tonight". When the DateTime object is on the time-line, a date whose time element has 24:00 coincides with the next day at 00:00. They are the same time-line instant with two different representations, both representations valid per ISO.
A Time-only value is detached from the time-line. A time of 00:00 occurs at the beginning of the detached 24-hour day and a Time-only value of 24:00 is 24 hours after 00:00. A Time type should accept 24 in the hour. When 24 is the hour the maximum value for seconds and milliseconds and ticks is 0 (unless modulo arithmetic is involved and the time rolls over, so that 24:01 is 00:01 -- but ISO has nothing to say about this implementation detail, IIRC).
We accept 24:00 when parsing a LocalDateTime, but not 24:01.
This was issue 153, implemented in revision f7ac0365d8ca.
Unfortunately this was after the 1.0 release, so you'll either need to grab the current code, or wait for 1.1 to be released (hopefully soon).
We don't currently accept it when parsing just a LocalTime. If you want that, please log a feature request - we'd probably look at it for 1.2 (which will have a lot of text features), although I'm not sure what the representation would look like. (LocalTime itself doesn't support the idea of "end-of-day midnight".)