trying to compute the time for Sun's next setting time, I obtain a value for tomorrow - but I'm computing while the Sun is surely above of the horizon!
m is my observing site; that's what I got on terminal:
>>> ephem.now()
2012/10/16 16:02:00
>>> print m.next_setting(ephem.Sun(), use_center=True)
2012/10/17 16:38:36
that's the time for tomorrow. Also:
>>> m.previous_setting(ephem.Sun()) < ephem.now()
False
>>> m.previous_setting(ephem.Sun())
2012/10/16 16:42:14
So previous_setting is in the future.
Where am I wrong?
The next_setting() and previous_setting() functions do not consult the current value of ephem.now(). Instead, they look for dates previous to or subsequent to the .date of the Observer object — so the results you are getting only happen in my own experiments here on my laptop if the observer .date somehow gets set to a day in the future. Here are the setting times that I get if I use exactly the date and time you supplied:
import ephem
m = ephem.Observer()
m.long = '7:42:00'
m.lat = '45:04:00'
m.date = '2012/10/16 16:02:00'
print m.next_setting(ephem.Sun(), use_center=True)
# --> 2012/10/16 16:40:27
print m.previous_setting(ephem.Sun())
# --> 2012/10/15 16:44:05
Could you try running this script and see what you get as a result? The ephem.__version__ that currently displays on my laptop is 3.7.5.1, just in case that is a difference between us.
So: if you see odd results like this, then instead of printing and comparing the value of ephem.now() with the sunset times, you need to investigate the relationship between the observer's .date attribute and the sunset times you get out. If you can produce a little sample script like the one I show above, that sets its own times, instead of relying on now() to show a mistake that PyEphem is making (since by the time I see your question, my now() is obviously a bit different from your original "now"!), then I'll do my best to track down the problem.
Related
EDIT: thanks to Alexander - Reinstate Monica. See the link in the comments for more info.
I ran into something odd today. I'm using firebase storage for an app and I want to compare the date of the file on the server with the one stored locally which I have manually set the attributes for when creating the file. If the dates are different then the app will re-load the file from the server like so:
if localModDate != serverModDate {
//re-download file
}
most of the time this works correctly, but sometimes the if statement get triggered even though the dates match (checked via print statements) and if I convert the stamps to strings then the dates always match correctly:
if String(describing: localModDate) != String(describing: serverModDate) {
//re-download file
}
my guess is that swift is converting to epoch time (I tested this and the epoch times are indeed off in like the 6th decimal place). Is this correct or is there something else going on here?
Date is just a TimeInterval (which is a typealias for Double) of elapsed seconds since the "reference date" (Jan 1 2001). The == operator just compares those two Doubles, so it's subject to the same floating point precision issues of regular Doubles.
Use Calendar.isDate(_:equalTo:toGranularity:) to check if the dates are "close enough":
if Calendar.current.isDate(localModDate, equalTo: serverModDate, toGranularity: .second) {
...
}
Before I spend a lot of time writing the only solution I can think of I was wondering if I'm doing it an inefficient way.
Once a support ticket is closed, a script is triggered, the script is passed an array of 'status-change-events' that happened from call open to close. So you might have 5 changes: new, open, active, stalled, resolved. Each one of these events has a timestamp associated with it.
What I need to do is calculate how much time the call was with us (new, open, active) and how much time it was with the customer (stalled). I also need to figure out how much of the 'us' time was within core hours 08:00 - 18:00 (and how many were non-core), and weekends/bank holidays count towards non-core hours.
My current idea is to for each status change, iterate over every second that occurred and check for core/non_core, and log it.
Here's some pseudo code:
time_since_last = ticket->creation_date
foreach events as event {
time_now = time_since_last
while (time_now < ticket->event_date) {
if ticket->status = stalled {
customer_fault_stalled++
} else {
work out if it was our fault or not
add to the appropriate counter etc
}
time_now++
}
}
Apologies if it's a little unclear, it's a fairly longwinded problem. Also I'm aware this may be slightly off of SO question guidelines, but I can't think of a better way of wording it and I need some advice before I spend days writing it this way.
I think you have the right idea, but recalculating the status of every ticket for every second of elapsed time will take a lot processing, and nothing will have changed for the vast majority of those one-second intervals
The way event simulations work, and the way I think you should write your application, is to create a list of all events where the status might change. So you will want to include all of the status change events for every ticket as well as the start and end of core time on all non-bank-holiday weekdays
That list of events is sorted by timestamp, after which you can just process each event as if your per-second counter has reached that time. The difference is that you no longer have to count through the many intervening seconds where nothing changes, and you should end up with a much more efficient application
I hope that's clear. You may find it easier to process each ticket separately, but the maximum gain will be achieved by processing all tickets simultaneously. You will still have a sorted sequence of events to process, but you will avoid having to reprocess the same core time start and end events over and over again
One more thing I noticed is that you can probably ignore any open status change events. I would guess that tickets either go from new to open and then active, or straight from new to resolved. So a switch between with your company and with the customer will never be made at an open event, and so they can be ignored. Please check this as I am only speaking from my intuition, and clearly know nothing about how your ticketing system has been designed
I would not iterate over the seconds. Depending on the cost of your calculations that could be quite costly. It would be better to calculate the borders between core/outside core.
use strict;
use warnings;
my $customer_time;
my $our_time_outside;
my $our_time_core;
foreach my $event ($ticket->events) {
my $current_ts = $event->start_ts;
while ($current_ts < $event->end_ts) {
if ($event->status eq 'stalled') {
$customer_time += $event->end_ts - $current_ts;
$current_ts = $event->end_ts;
}
elsif (is_core_hours($current_ts)) {
my $next_ts = min(end_of_core_hours($current_ts), $event->end_ts);
$our_time_core += $next_ts - $current_ts;
$current_ts = $next_ts;
}
else {
my $next_ts = min(start_of_core_hours($current_ts), $event->end_ts);
$our_time_outside += $next_ts - $current_ts;
$current_ts = $next_ts;
}
}
}
I can't see why you'd want to iterate over every second. That seems very wasteful.
Get a list of all of the events for a given ticket.
Add to the list any boundaries between core and non-core times.
Sort this list into chronological order.
For each consecutive pair of events in the list, subtract the later from the earlier to get a duration.
Add that duration to the appropriate bucket.
And the usual caveats for dealing with dates and times apply here:
Use a library (I recommend DateTime together with DateTime::Duration)
Convert all of your timestamps to UTC as soon as you get them. Only convert back to local time just before displaying them to the user.
My question is how can I get the same day, month, year, hour, minutes, seconds in a different time zone, for example:
var now = moment().valueOf();
var result1 = moment(now).format('DD-MM-YYYY HH:mm:SS Z');
In my time zone I get some this like this:
18-02-2015 21:08:34 +01:00
So how can I change only time zone without changing other values (days, months, ..., minutes, ...)
I want to get some thing like this:
result2: 18-02-2015 21:08:34 +01:00
result3: 18-02-2015 21:08:34 +10:00
result4: 18-02-2015 21:08:34 +05:00
result5: 18-02-2015 21:08:34 -06:00
result6: 18-02-2015 21:08:34 -11:00
Thanks in advance
Here's how you could do what you are asking:
// get a moment representing the current time
var now = moment();
// create a new moment based on the original one
var another = now.clone();
// change the offset of the new moment - passing true to keep the local time
another.utcOffset('+05:30', true);
// log the output
console.log(now.format()); // "2016-01-15T11:58:07-08:00"
console.log(another.format()); // "2016-01-15T11:58:07+05:30"
However, you must recognize two important things:
The another object no longer represents the current time - even in the target time zone. It's a completely different moment in time. (The world does not synchronize local clocks. If it did, we'd have no need for time zones!).
For this reason, even though the above code satisfies the question that was asked, I strongly recommend against using it. Instead, re-evaluate your requirements, as it's likely they are misunderstanding the nature of time and time zones.
A time zone cannot be fully represented by an offset alone. Read "Time Zone != Offset" in the timezone tag wiki. While some time zones have fixed offsets (such as +05:30 used by India), many time zones change their offsets at different points throughout the year to accommodate daylight saving time.
If you wanted to account for this, you could use moment-timezone instead of calling utcOffset(...). However, the issue in my first bullet would still apply.
// get a moment representing the current time
var now = moment();
// create a new moment based on the original one
var another = now.clone();
// change the time zone of the new moment - passing true to keep the local time
another.tz('America/New_York', true); // or whatever time zone you desire
// log the output
console.log(now.format()); // "2016-01-15T11:58:07-08:00"
console.log(another.format()); // "2016-01-15T11:58:07-05:00"
The most-voted answer is messy IMO. Here's a cleaner solution - similar to BlueSam's answer, but safer:
const myTime = moment.tz('2016-08-30T22:00:00', moment.ISO_8601, 'America/Denver')
myTime.format() //2016-08-30T22:00:00-06:00
const sameTimeDifferentZone = moment.tz(myTime.format('YYYY-MM-DDTHH:mm:ss.SSS'), moment.ISO_8601, 'America/New_York')
sameTimeDifferentZone.format() //2016-08-30T22:00:00-04:00
After reading the above comments, I thought I'd add in based on Joao's answer.
In my case I was trying to use a preexisting moment date with a timezone and converting it to another timezone while retaining the original date value (as asked in the question).
var newTimezone = 'America/Denver';
//date - contains existing moment with timezone i.e 'America/New_York'
moment.tz(date.format('YYYY-MM-DDTHH:mm:ss'), 'YYYY-MM-DDTHH:mm:ss', newTimezone);
From the moment docs: http://momentjs.com/timezone/docs/
reference moment-timezone-with-data.js and specify which timezone to go to, like so:
moment(date).tz("America/Los_Angeles").format()
Due to the limitation of date parsing on BlackBerry I'm trying to roll my own parse/deparse methods, however I seem to be falling foul of an hour's difference somewhere, somehow.
I do this:
long nowLong = System.currentTimeMillis();
String nowString = DateParser.longToString(nowLong);
Date nowDateFromString = DateParser.stringToDate(nowString);
Date nowDateFromLong = DateParser.longToDate(nowLong);
When outputted in order it produces this in console:
[139.46] 1369132556831
[139.46] 21 May 2013 11:35:56 Europe/Dublin
[139.46] Tue May 21 12:35:56 Europe/Dublin 2013
[139.46] Tue May 21 11:35:56 Europe/Dublin 2013
My simulator's time is set to 11:35 so the third statement - DateParser.stringToDate() - seems to be failing somewhere.
Here is my implementation:
public static Date stringToDate(String date) {
long l = HttpDateParser.parse(date);
Date d = new Date(l);
return d;
}
As my nowString includes the time zone I'd expect HttpDateParser.parse() to take this in to account but it seems not to be.
How can I correct this?
HttpDateParser.parse() is documented to handle "GMT" or a "TZD" which I assume to be a "time zone designator". I suspect this is expected to be the (horrible, ambiguous) abbreviation format - so for example, it might be worth trying to parse
21 May 2013 11:35:56 BST
and seeing what you get out. That would at least take you further in terms of diagnosing the behaviour of HttpDateParser. Keeping the time zone's TZDB ID is a better idea in my view, but you may well need to write your own parsing code. You still need to handle local time ambiguity though, where a particular local time occurs twice due to DST transitions.
It's not entirely clear what the input or expected output are in your case - how much control you have over the format. I'd try to use ISO-8601 as far as possible, with a time zone identifer as well if you need one. (If you're only trying to represent an instant in time, I'd use an ISO-8601 representation of the UTC instant, complete with a Z suffix to indicate UTC.)
I am trying to use the Joda Time library to help me schedule sending some messages to an Actor in Akka.
I would like to schedule sending emails every day at 8:30 AM. To do this, I have to tell the scheduler how many seconds (or milliseconds) to wait until the next message is sent.
I would like to account for daylight savings (to make sure it always fires around 8:30, and not 7:30 or 9:30) so I will use LocalDate and LocalTime.
So, basically, I have:
targetDate = LocalDate.now().plusDays(1) and targetTime = new LocalTime(8, 30)
and
rightNow = LocalDateTime.now()
I was wondering what is the best way to compose a targetDateTime based on targetDate and targetTime so I can use it to compute the time difference with rightNow
I know I can create a new LocalDateTime extracting all the values for the constructor from my targetDate and targetTime but: is there a more elegant way?
So far, I have settled for:
targetDateTime = targetDate.toLocalDateTime(targetTime)
secondsToWait = Seconds.secondsBetween(rightNow, targetDateTime)
Getting targetDateTime is easy if you have the targetDate and targetTime (as given in your question) :
targetDateTime = targetDate.toDateTime(targetTime);
Getting the seconds of the Duration between now and targetDateTime:
new Duration(new DateTime(), targetDateTime).getStandardSeconds();
The method is called standard seconds because it assumes every second to be a standard second of 1000 milliseconds. As its javadoc says, currently all Chronologies only have standard seconds.
But you can also simply use milliseconds (no conversion assumptions needed) :
new Duration(new DateTime(), targetDateTime).getMillis();
Disclaimer : I only just saw this was a scala question, so you may have to correct for any syntax differences, since I'm not versed in scala.