问:
Faster way to update an empty dataframe using the information from two dataframes
I  have two dataframes: df_a and df_b (each having a total of 1,000,000 rows).

df_a has two columns: uniqueID, start_time

df_b has two columns: uniqueID, end_time

My objective is to generate a dataframe (df_final) with following columns:

uniqueID, start_time, end_time

df_final must contains all the data from df_a (i.e. uniqueID, start_time). For each (uniqueID, start_time) in df_final, end_time must be taken from df_b corresponding to same uniqueID. df_b have multiple end_time for each uniqueID. For each uniqueID, end_time closest to start_time must be considered for df_final["end_time"]. In case, no such closest end_time is available in df_b, then df_final["end_time"] must be NULL.

My approaches:
Approach 1:

```<code>#define a function
def get_end_date(uniqueID, start_time):
    sub_sectiondata = df_b[(df_b['uniqueID']==uniqueID) & (df_b["end_time"]>start_time)]
    if len(sub_sectiondata) == 0:
        return None
    else:
        return min(sub_sectiondata["end_time"])
</code>```

Then apply the above function on df_a.

```<code>df_a['end_time'] = df_a.apply(lambda x: get_end_date(x['uniqueID'], x['start_time']), axis=1)
</code>```

Approach 2:

```<code>df = df_a.copy()

for row in df.itertuples():
    sub_sectiondata = df_b[(df_b['uniqueID']==row.uniqueID) & (df_b["end_time"]>row.start_time)]
    if len(sub_sectiondata)>0:
        df_final = df_final .append({'uniqueID':row.uniqueID, 'start_time':row.start_time, 'end_time': min(sub_sectiondata["end_time"])}, ignore_index = True)

    else:
        df_final = df_final .append({'uniqueID':row.uniqueID, 'start_time':row.start_time, 'end_time': None}, ignore_index = True)
</code>```

In both the approaches, I am getting the desired result, but the time taken to execute this is very high. It increases linearly (for every 10000 records, it takes approx 20 minutes). So for 1000000, it will be around 33 hours to complete which is huge. So is there any other method in python to handle this? Any help in this regard from the community?

答:
Maybe the logic takes up a lot of time because Pandas has to look over the whole dataframes several times. Try profiling to see what takes a long time (https://docs.python.org/2/library/profile.html + https://jiffyclub.github.io/snakeviz/ ).

What you can try is:

copy A

add a columns end_time with Null values

then iterate over B and if end_time is lower than the corresponding one in A with the same id you replace it.

That way you are only iterating over B once. This could be faster but it needs to be checked. If you provide me with an example dataset I can give it a shot.

I don't know if dataframes are the most efficient datastructure speedwise. Maybe using Numpy arrays directly it could be faster. If you are really desperate, Cython could be a way to speed things up as well but I have no experience with it.

Body:
I  have two dataframes: df_a and df_b (each having a total of 1,000,000 rows).

df_a has two columns: uniqueID, start_time

df_b has two columns: uniqueID, end_time

My objective is to generate a dataframe (df_final) with following columns:

uniqueID, start_time, end_time

df_final must contains all the data from df_a (i.e. uniqueID, start_time). For each (uniqueID, start_time) in df_final, end_time must be taken from df_b corresponding to same uniqueID. df_b have multiple end_time for each uniqueID. For each uniqueID, end_time closest to start_time must be considered for df_final["end_time"]. In case, no such closest end_time is available in df_b, then df_final["end_time"] must be NULL.

My approaches:
Approach 1:

#define a function
def get_end_date(uniqueID, start_time):
    sub_sectiondata = df_b[(df_b['uniqueID']==uniqueID) & (df_b["end_time"]>start_time)]
    if len(sub_sectiondata) == 0:
        return None
    else:
        return min(sub_sectiondata["end_time"])

Then apply the above function on df_a.

df_a['end_time'] = df_a.apply(lambda x: get_end_date(x['uniqueID'], x['start_time']), axis=1)

Approach 2:

df = df_a.copy()

for row in df.itertuples():
    sub_sectiondata = df_b[(df_b['uniqueID']==row.uniqueID) & (df_b["end_time"]>row.start_time)]
    if len(sub_sectiondata)>0:
        df_final = df_final .append({'uniqueID':row.uniqueID, 'start_time':row.start_time, 'end_time': min(sub_sectiondata["end_time"])}, ignore_index = True)

    else:
        df_final = df_final .append({'uniqueID':row.uniqueID, 'start_time':row.start_time, 'end_time': None}, ignore_index = True)

In both the approaches, I am getting the desired result, but the time taken to execute this is very high. It increases linearly (for every 10000 records, it takes approx 20 minutes). So for 1000000, it will be around 33 hours to complete which is huge. So is there any other method in python to handle this? Any help in this regard from the community?


来源: stackexchange

问:
c# daylight savings duplicate hour convert to UTC
I am using TimeZoneInfo to convert between client side wallclock 'Eastern Time' and UTC. My problem is with the 'duplicate' hour that occurs during autumn DST change.

During conversion from UTC to Eastern:

2010-11-07 06:00 UTC --> gives 2010-11-07T01:00:00-03:30

2010-11-07 07:00 UTC --> gives 2010-11-07T01:00:00-03:30

How can I know which is first hour and which is second?  DateTime.IsDaylightSavingTime() returns false for both hours, but shouldn't it return true for the first hour?

Likewise, how do I store 2010-11-07 01:00:00-03:30? How can my app convert to UTC since it could be 2010-11-07 06:00 or 2010-11-07 07:00

For those who need code, I am cycling through a datatable with UTC datetime column, trying to convert to Eastern with a 'DupHr' column for the second duplicate hour, but I always end up with both 01:00 hours having 'DupHr' = 1.

```<code>    TimeZoneInfo est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

    DateTime EasternTime;
    DateTime DuplicateHour = new DateTime(2010, 11, 7, 1, 0, 0);  // hard coded for this example
    TimeZoneInfo.AdjustmentRule[] rules =  est.GetAdjustmentRules();

    foreach (DataRow row in dt.Rows)
    {
        row["DupHr"] = 0;  // by default not duplicate hour
        EasternTime = TimeZoneInfo.ConvertTimeFromUtc((DateTime)row[UTCColumnName], est);
        if (!EasternTime.IsDaylightSavingTime())
        {
            if (EasternTime.Equals(DuplicateHour ))
            {
                row["DupHr"] = 1;   // This is the second duplicate hour !
            }
        } else

            EasternTime.Add(rules[1].DaylightDelta);  // Add DST offset from rule #1

        row[newESTColumnName] = EasternTime;
    }
</code>```

THANKS!

Solution

It is important to know more than 'ambiguous' for the duplicate hours.  The hours must be unique (first and second).  Consider a toll booth money counter application which must operate 24x7 and totalize each hour's collection.   Money collected in each hour must be identifiable.   First hour 1:00 to 1:59 is different from second 1:00 to 1:59 hour.   The routine below isSecondHour will return true only if the passed time is in second hour of autumn DST change.  The user interface can display this flag appropriately.

```<code> // Get the DST rule for the year and zone  (rules may change from year to year as in 2004)
    public static TimeZoneInfo.AdjustmentRule GetDSTrule(int Year, TimeZoneInfo zone)
    {
        TimeZoneInfo.AdjustmentRule[] rules = zone.GetAdjustmentRules();

        foreach (TimeZoneInfo.AdjustmentRule rul in rules)
        {
            if (rul.DateStart < new DateTime(Year, 1, 1) && rul.DateEnd > new DateTime(Year, 1, 1))
            {
                return rul;
            }
        }
        return null;
    }

    // Determine if 'localtime' is in the second duplicate DST hour.
    public static Boolean isSecondHour(TimeZoneInfo localzone, DateTime localtime, DateTime UTCtime)
    {

        if (localzone.IsAmbiguousTime(localtime))
        {
            TimeZoneInfo.AdjustmentRule rul = GetDSTrule(localtime.Year, localzone);
            return UTCtime.Add(localzone.GetUtcOffset(localtime)) == localtime;
        }
        else
            return false;
    }

    static void Main(string[] args)
    {
        var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

        var times = new DateTime[] {
        new DateTime (2010, 11, 7, 3,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 4,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 5,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 5,  30, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 6,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 6,  30, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 7,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 8,  0, 0, DateTimeKind.Unspecified)

    };

    DateTime EasternTime;
    Console.WriteLine("UTC Time  |  Est Time   | IsDaylightSaving | IsAmbiguousTime | isSecondHour ");

    foreach (var utc in times)
    {
        // Get Eastern Time from UTC using standard convert routine.
        EasternTime = TimeZoneInfo.ConvertTimeFromUtc(utc, est);
        Console.WriteLine("{0:HH:mm}     |   {1:HH:mm}     | {2,11}      |      {3,5}      |      {4,5}", utc,EasternTime, est.IsDaylightSavingTime(EasternTime), est.IsAmbiguousTime(EasternTime),isSecondHour(est,EasternTime, utc));
     }
</code>```

results

```<code>UTC Time  |  Est Time   | IsDaylightSaving | IsAmbiguousTime | isSecondHour
03:00     |   23:00     |        True      |      False      |      False
04:00     |   00:00     |        True      |      False      |      False
05:00     |   01:00     |       False      |       True      |      False
05:30     |   01:30     |       False      |       True      |      False
06:00     |   01:00     |       False      |       True      |       True
06:30     |   01:30     |       False      |       True      |       True
07:00     |   02:00     |       False      |      False      |      False
08:00     |   03:00     |       False      |      False      |      False
</code>```

答:
Summary

You can't know, because by not storing the offset you've lost an important piece of information, the time zone the time was originally in, which as you've pointed out could be either Eastern Standard Time or Eastern Daylight Time.

Detecting the ambiguous time

TimeZoneInfo provides the method IsAmbiguousTime to check if this might be the case.

The problem with your detection for this ambiguous time is you're trying to use IsDaylightSavings which returns false for ambiguous times, as illustrated by this example:

```<code>var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

var times = new DateTime[] {
    new DateTime (2010, 11, 7, 4,  0, 0, DateTimeKind.Utc),
    new DateTime (2010, 11, 7, 5,  0, 0, DateTimeKind.Utc),
    new DateTime (2010, 11, 7, 5, 30, 0, DateTimeKind.Utc),
    new DateTime (2010, 11, 7, 6,  0, 0, DateTimeKind.Utc),
};

Console.WriteLine("     Time  | IsDaylightSaving | IsAmbiguousTime");
foreach (var t in times) {
    var time = TimeZoneInfo.ConvertTimeFromUtc(t, est);
    Console.WriteLine ("    {0:HH:mm}  | {1,11}      |      {2,5}", time, est.IsDaylightSavingTime(time), est.IsAmbiguousTime(time));
}
</code>```

Result:

```<code> Time  | IsDaylightSaving | IsAmbiguousTime
00:00  |        True      |      False
01:00  |       False      |       True
01:30  |       False      |       True
01:00  |       False      |       True
</code>```

So you want to be using est.IsAmbiguousTime(EasternTime). Then there is no need for DuplicateHour as this will cover the full time range that is ambiguous on that day.
DateTimeOffset does not suffer this problem due to it explicitly storing the offset.

Converting EST to UTC and storing in the database

For your initial conversion from EST to UTC of the existing data in the database will want to store the offset for future use. For non-ambiguous times this can be retrieved from the timezone. However, as you have identified, for ambiguous times this information will not be available. For these times you will have to assume which offset to use and flag the time in the DB as suspect so the UI can react accordingly when displaying these times.

Depending on how much data is affected it might not be worth the effort of changing the UI and to simply ignore the problem, especially if it really isn't that important to a user if the time is out by an hour (since on the user's screen in that timezone it would still display as 1am). The DB will still record that the time was suspect if you ever later change your mind.

Converting from UTC to EST and detecting ambiguous times

Firstly, use DateTimeOffset as this can tell the difference between 1am EST, and 1am EDT. At which point TimeZoneInfo.IsAmbiguousTime(DateTimeOffset) can be used to highlight the duplicate times on screen, and TimeZoneInfo.IsDaylightSavings(DateTimeOffset) will also correctly return true or false.

```<code>var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

var times = new DateTimeOffset[] {
    new DateTimeOffset (2010, 11, 7, 4, 00, 0, TimeSpan.Zero),
    new DateTimeOffset (2010, 11, 7, 5, 00, 0, TimeSpan.Zero),
    new DateTimeOffset (2010, 11, 7, 5, 30, 0, TimeSpan.Zero),
    new DateTimeOffset (2010, 11, 7, 6, 00, 0, TimeSpan.Zero),
};

Console.WriteLine("     Time  | IsDaylightSaving | IsAmbiguousTime");
foreach (var t in times) {
    var time = TimeZoneInfo.ConvertTime (t, est);
    Console.WriteLine ("    {0:HH:mm}  | {1,11}      |      {2,5}", time, est.IsDaylightSavingTime(time), est.IsAmbiguousTime(time));
}
</code>```

Result:

```<code> Time  | IsDaylightSaving | IsAmbiguousTime
00:00  |        True      |      False
01:00  |        True      |       True
01:30  |        True      |       True
01:00  |       False      |       True
</code>```

Future Considerations

User interface issues

When displaying to a user, it shouldn't matter if the local time is ambiguous or not (duplicate hour). You can simply convert the UTC time to their timezone and format as a string. You might want to check IsAmbiguousTime to display a hint to the user why they might be seeing "1am" twice. Sorting the information by date should be done using UTC. Going from UTC to a local time should never be ambiguous, since each point in time only exists once in UTC, there are no duplicate hours.

So the only problem now, is if the user is entering a time and you need to interpret what time they meant, as the user is unlikely to enter an offset or even care about such details. Sadly there is no simple way of handling this and short of trying to teach your users about offsets they will make mistakes and enter the wrong time. Eg they might enter 4am thinking 4 hours past midnight, forgetting that on that night there is 1 hour extra/less. Alternatively they could enter 3am on a day when the clocks go forwards at 3am, which on that day is a time that simply doesn't exist.

Fortunately the time the clocks changed is aimed to minimize the user input problem as most people are asleep. So the system could take a best guess and accept being out by an hour sometimes. If it really matters then you could check if that day has daylight savings and show a different UI with a warning/prompt.

Storage and transfer

If storing the time in MSSQL server the datetimeoffset should be preferred as this can handle storing both the time and offset. When using this type MSSQL server can handle comparing times with different offsets correctly.

For databases that do not support such a type, you can store the time in UTC in the database, and store the offset for that time in a separate column. This will allow you to accurately know the local time it was recorded at.

When exchanging with external systems, then ideally transfer the time as local in format yyyy-MM-dd HH:mm:sszzzz (eg 2010-11-07 01:00:00-03:30) so that both the time and offset can be preserved. Otherwise UTC is normally the best choice but ideally should have be suffixed with 'Z' or '+00:00' to make this obvious.

In memory, the DateTimeOffset class is a better choice because it can represent any arbitary offset compared to DateTime which can only represent UTC or the system's local time.

Note, the accuracy of TimeZoneInfo's daylight savings depends on OS version, service packs and windows updates applied.

Also, it matters how daylights savings is applied. If they are applied by the OS using the "Automatically adjust clock for daylight savings" then the offset will be adjusted correctly. If the admin has disabled this and manually adjusts the time by adding/subtracting an hour then the OS will be unaware of this and will be operating with the wrong offset. See, TimeZoneInfo.Local for other notes regarding this OS setting.

ContentLicense: CC BY-SA 3.0

Body:
I am using TimeZoneInfo to convert between client side wallclock 'Eastern Time' and UTC. My problem is with the 'duplicate' hour that occurs during autumn DST change.

During conversion from UTC to Eastern:

2010-11-07 06:00 UTC --> gives 2010-11-07T01:00:00-03:30

2010-11-07 07:00 UTC --> gives 2010-11-07T01:00:00-03:30

How can I know which is first hour and which is second?  DateTime.IsDaylightSavingTime() returns false for both hours, but shouldn't it return true for the first hour?

Likewise, how do I store 2010-11-07 01:00:00-03:30? How can my app convert to UTC since it could be 2010-11-07 06:00 or 2010-11-07 07:00

For those who need code, I am cycling through a datatable with UTC datetime column, trying to convert to Eastern with a 'DupHr' column for the second duplicate hour, but I always end up with both 01:00 hours having 'DupHr' = 1.

    TimeZoneInfo est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

    DateTime EasternTime;
    DateTime DuplicateHour = new DateTime(2010, 11, 7, 1, 0, 0);  // hard coded for this example
    TimeZoneInfo.AdjustmentRule[] rules =  est.GetAdjustmentRules();

    foreach (DataRow row in dt.Rows)
    {
        row["DupHr"] = 0;  // by default not duplicate hour
        EasternTime = TimeZoneInfo.ConvertTimeFromUtc((DateTime)row[UTCColumnName], est);
        if (!EasternTime.IsDaylightSavingTime())
        {
            if (EasternTime.Equals(DuplicateHour ))
            {
                row["DupHr"] = 1;   // This is the second duplicate hour !
            }
        } else

            EasternTime.Add(rules[1].DaylightDelta);  // Add DST offset from rule #1

        row[newESTColumnName] = EasternTime;
    }

THANKS!

Solution

It is important to know more than 'ambiguous' for the duplicate hours.  The hours must be unique (first and second).  Consider a toll booth money counter application which must operate 24x7 and totalize each hour's collection.   Money collected in each hour must be identifiable.   First hour 1:00 to 1:59 is different from second 1:00 to 1:59 hour.   The routine below isSecondHour will return true only if the passed time is in second hour of autumn DST change.  The user interface can display this flag appropriately.

 // Get the DST rule for the year and zone  (rules may change from year to year as in 2004)
    public static TimeZoneInfo.AdjustmentRule GetDSTrule(int Year, TimeZoneInfo zone)
    {
        TimeZoneInfo.AdjustmentRule[] rules = zone.GetAdjustmentRules();

        foreach (TimeZoneInfo.AdjustmentRule rul in rules)
        {
            if (rul.DateStart < new DateTime(Year, 1, 1) && rul.DateEnd > new DateTime(Year, 1, 1))
            {
                return rul;
            }
        }
        return null;
    }

    // Determine if 'localtime' is in the second duplicate DST hour.
    public static Boolean isSecondHour(TimeZoneInfo localzone, DateTime localtime, DateTime UTCtime)
    {

        if (localzone.IsAmbiguousTime(localtime))
        {
            TimeZoneInfo.AdjustmentRule rul = GetDSTrule(localtime.Year, localzone);
            return UTCtime.Add(localzone.GetUtcOffset(localtime)) == localtime;
        }
        else
            return false;
    }

    static void Main(string[] args)
    {
        var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

        var times = new DateTime[] {
        new DateTime (2010, 11, 7, 3,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 4,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 5,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 5,  30, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 6,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 6,  30, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 7,  0, 0, DateTimeKind.Unspecified),
        new DateTime (2010, 11, 7, 8,  0, 0, DateTimeKind.Unspecified)

    };

    DateTime EasternTime;
    Console.WriteLine("UTC Time  |  Est Time   | IsDaylightSaving | IsAmbiguousTime | isSecondHour ");

    foreach (var utc in times)
    {
        // Get Eastern Time from UTC using standard convert routine.
        EasternTime = TimeZoneInfo.ConvertTimeFromUtc(utc, est);
        Console.WriteLine("{0:HH:mm}     |   {1:HH:mm}     | {2,11}      |      {3,5}      |      {4,5}", utc,EasternTime, est.IsDaylightSavingTime(EasternTime), est.IsAmbiguousTime(EasternTime),isSecondHour(est,EasternTime, utc));
     }

results

UTC Time  |  Est Time   | IsDaylightSaving | IsAmbiguousTime | isSecondHour
03:00     |   23:00     |        True      |      False      |      False
04:00     |   00:00     |        True      |      False      |      False
05:00     |   01:00     |       False      |       True      |      False
05:30     |   01:30     |       False      |       True      |      False
06:00     |   01:00     |       False      |       True      |       True
06:30     |   01:30     |       False      |       True      |       True
07:00     |   02:00     |       False      |      False      |      False
08:00     |   03:00     |       False      |      False      |      False

Body:
Summary

You can't know, because by not storing the offset you've lost an important piece of information, the time zone the time was originally in, which as you've pointed out could be either Eastern Standard Time or Eastern Daylight Time.

Detecting the ambiguous time

TimeZoneInfo provides the method IsAmbiguousTime to check if this might be the case.

The problem with your detection for this ambiguous time is you're trying to use IsDaylightSavings which returns false for ambiguous times, as illustrated by this example:

var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

var times = new DateTime[] {
    new DateTime (2010, 11, 7, 4,  0, 0, DateTimeKind.Utc),
    new DateTime (2010, 11, 7, 5,  0, 0, DateTimeKind.Utc),
    new DateTime (2010, 11, 7, 5, 30, 0, DateTimeKind.Utc),
    new DateTime (2010, 11, 7, 6,  0, 0, DateTimeKind.Utc),
};

Console.WriteLine("     Time  | IsDaylightSaving | IsAmbiguousTime");
foreach (var t in times) {
    var time = TimeZoneInfo.ConvertTimeFromUtc(t, est);
    Console.WriteLine ("    {0:HH:mm}  | {1,11}      |      {2,5}", time, est.IsDaylightSavingTime(time), est.IsAmbiguousTime(time));
}

Result:

 Time  | IsDaylightSaving | IsAmbiguousTime
00:00  |        True      |      False
01:00  |       False      |       True
01:30  |       False      |       True
01:00  |       False      |       True

So you want to be using est.IsAmbiguousTime(EasternTime). Then there is no need for DuplicateHour as this will cover the full time range that is ambiguous on that day.
DateTimeOffset does not suffer this problem due to it explicitly storing the offset.

Converting EST to UTC and storing in the database

For your initial conversion from EST to UTC of the existing data in the database will want to store the offset for future use. For non-ambiguous times this can be retrieved from the timezone. However, as you have identified, for ambiguous times this information will not be available. For these times you will have to assume which offset to use and flag the time in the DB as suspect so the UI can react accordingly when displaying these times.

Depending on how much data is affected it might not be worth the effort of changing the UI and to simply ignore the problem, especially if it really isn't that important to a user if the time is out by an hour (since on the user's screen in that timezone it would still display as 1am). The DB will still record that the time was suspect if you ever later change your mind.

Converting from UTC to EST and detecting ambiguous times

Firstly, use DateTimeOffset as this can tell the difference between 1am EST, and 1am EDT. At which point TimeZoneInfo.IsAmbiguousTime(DateTimeOffset) can be used to highlight the duplicate times on screen, and TimeZoneInfo.IsDaylightSavings(DateTimeOffset) will also correctly return true or false.

var est = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

var times = new DateTimeOffset[] {
    new DateTimeOffset (2010, 11, 7, 4, 00, 0, TimeSpan.Zero),
    new DateTimeOffset (2010, 11, 7, 5, 00, 0, TimeSpan.Zero),
    new DateTimeOffset (2010, 11, 7, 5, 30, 0, TimeSpan.Zero),
    new DateTimeOffset (2010, 11, 7, 6, 00, 0, TimeSpan.Zero),
};

Console.WriteLine("     Time  | IsDaylightSaving | IsAmbiguousTime");
foreach (var t in times) {
    var time = TimeZoneInfo.ConvertTime (t, est);
    Console.WriteLine ("    {0:HH:mm}  | {1,11}      |      {2,5}", time, est.IsDaylightSavingTime(time), est.IsAmbiguousTime(time));
}

Result:

 Time  | IsDaylightSaving | IsAmbiguousTime
00:00  |        True      |      False
01:00  |        True      |       True
01:30  |        True      |       True
01:00  |       False      |       True

Future Considerations

User interface issues

When displaying to a user, it shouldn't matter if the local time is ambiguous or not (duplicate hour). You can simply convert the UTC time to their timezone and format as a string. You might want to check IsAmbiguousTime to display a hint to the user why they might be seeing "1am" twice. Sorting the information by date should be done using UTC. Going from UTC to a local time should never be ambiguous, since each point in time only exists once in UTC, there are no duplicate hours.

So the only problem now, is if the user is entering a time and you need to interpret what time they meant, as the user is unlikely to enter an offset or even care about such details. Sadly there is no simple way of handling this and short of trying to teach your users about offsets they will make mistakes and enter the wrong time. Eg they might enter 4am thinking 4 hours past midnight, forgetting that on that night there is 1 hour extra/less. Alternatively they could enter 3am on a day when the clocks go forwards at 3am, which on that day is a time that simply doesn't exist.

Fortunately the time the clocks changed is aimed to minimize the user input problem as most people are asleep. So the system could take a best guess and accept being out by an hour sometimes. If it really matters then you could check if that day has daylight savings and show a different UI with a warning/prompt.

Storage and transfer

If storing the time in MSSQL server the datetimeoffset should be preferred as this can handle storing both the time and offset. When using this type MSSQL server can handle comparing times with different offsets correctly.

For databases that do not support such a type, you can store the time in UTC in the database, and store the offset for that time in a separate column. This will allow you to accurately know the local time it was recorded at.

When exchanging with external systems, then ideally transfer the time as local in format yyyy-MM-dd HH:mm:sszzzz (eg 2010-11-07 01:00:00-03:30) so that both the time and offset can be preserved. Otherwise UTC is normally the best choice but ideally should have be suffixed with 'Z' or '+00:00' to make this obvious.

In memory, the DateTimeOffset class is a better choice because it can represent any arbitary offset compared to DateTime which can only represent UTC or the system's local time.

Note, the accuracy of TimeZoneInfo's daylight savings depends on OS version, service packs and windows updates applied.

Also, it matters how daylights savings is applied. If they are applied by the OS using the "Automatically adjust clock for daylight savings" then the offset will be adjusted correctly. If the admin has disabled this and manually adjusts the time by adding/subtracting an hour then the OS will be unaware of this and will be operating with the wrong offset. See, TimeZoneInfo.Local for other notes regarding this OS setting.


问:
How to insert/update accented special characters in laravel
I am trying to insert / update accented special characters through Laravel

like

çã, á, é, í, ó, ú, ü, ñ

and many more.

But laravel is converting into some hex code and insert it into database. Which in return, i am getting content in chinese...

For example:-
i am trying to this

Actual query runs in laravel

What shown in blade is

I am using SQL-Server-2008

Data type of column is nvarchar and collation is SQL_Latin1_General_CP1_CI_AI

So, what i have conclude is,
this is the laravel issue becuase if run query directly in database by prefixing N like

set 'name' = N'Vishal çã, á, é, í, ó, ú, ü, ñ'

then it works fine.

How could we acheive this through laravel ?

答: If you are using Spanish language better use utf8mu_spanish_ci in your conf/database.php </p>

ContentLicense: CC BY-SA 4.0


问:
Get Data From text file on CodeIgniter
I just create a project, and I want to get data from server with .text format. I want to get specific data from it. I work with CodeIgniter. I need your advice or link to read. I've read at CodeIgniter user guide, but the data so small.

Thank you for everything.

答: Try file_get_contents() to get file contents directly to your variable. No CI-specific code needed at this point.</p>

Title: Get Data From text file on CodeIgniter


问:
Selecting multiple images using xam.plugin.media
I'm using xam.plugin.media to get the file path of the image selected. Working with a single image is fine, but I'm having trouble selecting multiple images.

This is my code:

```<code>List<MediaFile> mediaFile;
...
private async void AddAttachments(object sender, EventArgs e) {
            await CrossMedia.Current.Initialize();
            if (!CrossMedia.Current.IsPickPhotoSupported) {
                await DisplayAlert("Error", "Your phone does not support photo uploads. Please proceed without attachments.", "Okay");
                return;
            }

            mediaFile = await CrossMedia.Current.PickPhotosAsync();

            if (mediaFile == null) {
                return;
            }

        }
</code>```

Despite using PickPhotosAsync(), it still selects a single photo. I was expecting something where I can check images I want to upload like other mobile applications.

答:
Unfortunately, you can't (kind of). It is supposed to be working, but there was an issue about this back in 2018-2019, which got marked as solved, even though the user kept complaining about it not working reliably/always.
Link to the feature request/issue here.

There is a new issue, that got registered recently (April 2020) here.

My advice is to subscribe to it and comment, so that the developer will know that you are experiencing some issues with this functionality also. If you can, you can also create a sample project and upload it, so that they can quickly fix it.

However, in my experience, this package hasn't been frequently updated, so you might have to wait a bit.

Body:
I'm using xam.plugin.media to get the file path of the image selected. Working with a single image is fine, but I'm having trouble selecting multiple images.

This is my code:

List<MediaFile> mediaFile;
...
private async void AddAttachments(object sender, EventArgs e) {
            await CrossMedia.Current.Initialize();
            if (!CrossMedia.Current.IsPickPhotoSupported) {
                await DisplayAlert("Error", "Your phone does not support photo uploads. Please proceed without attachments.", "Okay");
                return;
            }

            mediaFile = await CrossMedia.Current.PickPhotosAsync();

            if (mediaFile == null) {
                return;
            }

        }

Despite using PickPhotosAsync(), it still selects a single photo. I was expecting something where I can check images I want to upload like other mobile applications.


问:
Counting with python dictionaries and adding functionality
```<code> a = 0
 b = 0
 c = 0
 d = 0

fruit = {
'lemons': [],
'apples': [],
'cherries': [],
'oranges': [],
 }

def count():
    fruit = input("What fruit are you getting at the store? ")
    if fruit == 'lemons':
        fruit['lemons'] = a + 1
    elif fruit == 'apples':
                fruit['apples'] = b + 1
    elif fruit == 'cherries':
                fruit['cherries'] = c + 1

    elif fruit == 'oranges':
                fruit['oranges'] = d + 1
    else: ????
</code>```

Hey, I'm trying to do two things here: 1) count how many occurrences of a certain word (in this case, certain types of fruit), appear in a document- which I am attempting to simulate here with a simple input function. I know it's not perfect, but I can't figure out how to make each occurrence increase the value for the appropriate key incrementally. For instance, if I call this function twice and type "lemons", the count should be 2, but it remains 1. In other words, my function is a lemon, but I don't know why.

The last thing I am having trouble with is the else function. 2 ) My program will be looking in pre-defined sections of a document, and I would like my else function to create a key: value pair in the dictionary if the existing key does not exist. For instance, if my program encounters the word 'banana', I would like to add the k:v pair { 'banana': [] } to the current dictionary so I can start counting those occurrences. But it seems like this would require me to not only add the k:v pair to the dictionary (which I don't rightly know how to do), but to add a function and variable to count the occurrences like the other k:v pairs.

Does this entire set up make sense for what I'm trying to do? Please help.

答:
You might do it by this way:    </p>

```<code>fruits = {
    'lemons': 0,
    'apples': 0,
    'cherries': 0,
    'oranges': 0,
}

fruit = input("What fruit are you getting at the store? ")

if fruits.has_key(fruit):
   fruits[fruit] += 1
</code>```

Body:
 a = 0
 b = 0
 c = 0
 d = 0

fruit = {
'lemons': [],
'apples': [],
'cherries': [],
'oranges': [],
 }

def count():
    fruit = input("What fruit are you getting at the store? ")
    if fruit == 'lemons':
        fruit['lemons'] = a + 1
    elif fruit == 'apples':
                fruit['apples'] = b + 1
    elif fruit == 'cherries':
                fruit['cherries'] = c + 1

    elif fruit == 'oranges':
                fruit['oranges'] = d + 1
    else: ????

Hey, I'm trying to do two things here: 1) count how many occurrences of a certain word (in this case, certain types of fruit), appear in a document- which I am attempting to simulate here with a simple input function. I know it's not perfect, but I can't figure out how to make each occurrence increase the value for the appropriate key incrementally. For instance, if I call this function twice and type "lemons", the count should be 2, but it remains 1. In other words, my function is a lemon, but I don't know why.

The last thing I am having trouble with is the else function. 2 ) My program will be looking in pre-defined sections of a document, and I would like my else function to create a key: value pair in the dictionary if the existing key does not exist. For instance, if my program encounters the word 'banana', I would like to add the k:v pair { 'banana': [] } to the current dictionary so I can start counting those occurrences. But it seems like this would require me to not only add the k:v pair to the dictionary (which I don't rightly know how to do), but to add a function and variable to count the occurrences like the other k:v pairs.

Does this entire set up make sense for what I'm trying to do? Please help.

Body:
You might do it by this way:

fruits = {
    'lemons': 0,
    'apples': 0,
    'cherries': 0,
    'oranges': 0,
}

fruit = input("What fruit are you getting at the store? ")

if fruits.has_key(fruit):
   fruits[fruit] += 1


问:
mock jooq select request
I have my service with jooq select in myMethod()

```<code>Result<MyRecord> records = dsl.selectFrom(MyTable).fetch();
</code>```

And I try to write unit-test using mockito. I want to mock my dsl and get 2 different result when I call service.myMethod()

```<code>Mockito.when(dsl.selectFrom(MyTable)).thenReturn(result)
</code>```

But it doesn't work. How can I mock my select request?

答:
Mocking the jOOQ API

If you want to mock the jOOQ API, the interesting methods for you to mock are the various fetch() methods, or execute() methods, as they act like the "terminal" methods of the jOOQ DSL API. All the intermediate methods should produce new mocks, not actual results.

However, as jOOQ's DSL is vast, you might be overlooking a variety of edge cases, so I think that mocking it entirely might not work too well.

Mocking the JDBC API

If you really want to mock the jOOQ API, I would rather mock it on the JDBC level. jOOQ implements a mock JDBC Connection, allowing to mock the entirety of JDBC using a single lambda expression, where you can do something like this (from the manual):

MockDataProvider provider = new MyProvider();
MockConnection connection = new MockConnection(provider);
DSLContext ctx = DSL.using(connection, SQLDialect.ORACLE);
Result<BookRecord> result = ctx.selectFrom(BOOK).where(BOOK.ID.eq(5)).fetch();
```

<p>And then (simplified):</p>

<pre class="lang-java prettyprint-override"><code>public class MyProvider implements MockDataProvider {

    @Override
    public MockResult[] execute(MockExecuteContext ctx) throws SQLException {
        DSLContext ctx = DSL.using(SQLDialect.ORACLE);
        MockResult[] mock = new MockResult[1];
        String sql = ctx.sql();

        if (sql.toUpperCase().startsWith("DROP")) {
            throw new SQLException("Statement not supported: " + sql);
        }
        else if (sql.toUpperCase().startsWith("SELECT")) {
            Result<Record2<Integer, String>> result =
                ctx.newResult(AUTHOR.ID, AUTHOR.LAST_NAME);
            result.add(cctx
                .newRecord(AUTHOR.ID, AUTHOR.LAST_NAME)
                .values(1, "Orwell"));
            mock[0] = new MockResult(1, result);
        }

        return mock;
    }
}
</code>```

There's also an out of the box, file-based version of this mock implementation, the MockFileDatabase, which uses regular expressions to match SQL strings and provides a text based syntax to construct result sets for your queries.

Mocking databases in general

Please beware that mocking is not a good way to test database interaction - it only gets you so far, in simple cases. A much better, thorough, approach are integration tests. If you must, using an in-memory database, but ideally using your production database product (e.g. Oracle, PostgreSQL, etc.) via something like testcontainers.

Title: mock jooq select request

Body:
I have my service with jooq select in myMethod()

Result<MyRecord> records = dsl.selectFrom(MyTable).fetch();

And I try to write unit-test using mockito. I want to mock my dsl and get 2 different result when I call service.myMethod()

Mockito.when(dsl.selectFrom(MyTable)).thenReturn(result)

But it doesn't work. How can I mock my select request?

Body:
Mocking the jOOQ API

If you want to mock the jOOQ API, the interesting methods for you to mock are the various fetch() methods, or execute() methods, as they act like the "terminal" methods of the jOOQ DSL API. All the intermediate methods should produce new mocks, not actual results.

However, as jOOQ's DSL is vast, you might be overlooking a variety of edge cases, so I think that mocking it entirely might not work too well.

Mocking the JDBC API

If you really want to mock the jOOQ API, I would rather mock it on the JDBC level. jOOQ implements a mock JDBC Connection, allowing to mock the entirety of JDBC using a single lambda expression, where you can do something like this (from the manual):

MockDataProvider provider = new MyProvider();
MockConnection connection = new MockConnection(provider);
DSLContext ctx = DSL.using(connection, SQLDialect.ORACLE);
Result<BookRecord> result = ctx.selectFrom(BOOK).where(BOOK.ID.eq(5)).fetch();

And then (simplified):

public class MyProvider implements MockDataProvider {

    @Override
    public MockResult[] execute(MockExecuteContext ctx) throws SQLException {
        DSLContext ctx = DSL.using(SQLDialect.ORACLE);
        MockResult[] mock = new MockResult[1];
        String sql = ctx.sql();

        if (sql.toUpperCase().startsWith("DROP")) {
            throw new SQLException("Statement not supported: " + sql);
        }
        else if (sql.toUpperCase().startsWith("SELECT")) {
            Result<Record2<Integer, String>> result =
                ctx.newResult(AUTHOR.ID, AUTHOR.LAST_NAME);
            result.add(cctx
                .newRecord(AUTHOR.ID, AUTHOR.LAST_NAME)
                .values(1, "Orwell"));
            mock[0] = new MockResult(1, result);
        }

        return mock;
    }
}

There's also an out of the box, file-based version of this mock implementation, the MockFileDatabase, which uses regular expressions to match SQL strings and provides a text based syntax to construct result sets for your queries.

Mocking databases in general

Please beware that mocking is not a good way to test database interaction - it only gets you so far, in simple cases. A much better, thorough, approach are integration tests. If you must, using an in-memory database, but ideally using your production database product (e.g. Oracle, PostgreSQL, etc.) via something like testcontainers.


问:
what's the difference between interface pointer and interface value in golang
when Node is a struct type, it can't compiled.

but when Node is a interface type it's ok.

why?

type Node interface {
}
// test1's parameter are pointer
func test1(b *Node) {
    test2(b)
}
// test2's parameter are not pointer
func test2(c Node) {}
```

答:
To answer the question in your title: an interface pointer is a pointer to an interface value.  However, an interface pointer is not that useful as an interface is a reference type already.

As to why your code does not compile when Node is a struct, you are trying to pass a pointer to a function that takes a value.  You should do this instead:

```<code>func test1(b *Node) {
    test2(*b)
}
</code>```

But when Node is an empty interface the parameter of test2() is of type interface{} also called the empty interface.  Any type (including b which is a pointer) will be implicitly converted to an empty interface.  Hence passing anything to test2() will compile when its parameter is of type interface{}.

Body:
To answer the question in your title: an interface pointer is a pointer to an interface value.  However, an interface pointer is not that useful as an interface is a reference type already.

As to why your code does not compile when Node is a struct, you are trying to pass a pointer to a function that takes a value.  You should do this instead:

func test1(b *Node) {
    test2(*b)
}

But when Node is an empty interface the parameter of test2() is of type interface{} also called the empty interface.  Any type (including b which is a pointer) will be implicitly converted to an empty interface.  Hence passing anything to test2() will compile when its parameter is of type interface{}.


问:
Failed to pass a string from Activity to Fragment
I want to pass a Serializable object from activity to fragment. But at fragment, getArguments() always retuns null. Then I try to pass a simple string value from activity to fragment, it still shows NullPointerExection.

Here is my Activity Class

```<code>public class FullProfile extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private Customer customer;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_full_profile);

    tabLayout = findViewById(R.id.tabLayout);
    viewPager = findViewById(R.id.myViewPager);
    setupViewPager(viewPager);

    ProfileBasicFragment basic = new ProfileBasicFragment();
    Bundle bundle = new Bundle();
    bundle.putString("profile", "Hello Hello");

    basic.setArguments(bundle);
    getSupportFragmentManager().beginTransaction().add(R.id.myViewPager, basic).commit();

    tabLayout.setupWithViewPager(viewPager);

}

private void setupViewPager(ViewPager viewPager) {
    FragmentAdapter fragmentAdapter = new FragmentAdapter(getSupportFragmentManager(), 4);
    fragmentAdapter.addFragment(new ProfileBasicFragment(), "Profile");
    fragmentAdapter.addFragment(new ProductFragment(), "Product");
    fragmentAdapter.addFragment(new WatchListFragment(), "Choices");

    viewPager.setAdapter(fragmentAdapter);

}
</code>```

}

Here is my Fragment..

```<code>public class ProfileBasicFragment extends Fragment {

TextView t;
String s;

public ProfileBasicFragment() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_profile_basic, container, false);
    t = view.findViewById(R.id.nameTV);

    String s = getArguments().getString("profile");
    t.setText(s);

    return view;
}
</code>```

}

And Here is the error

```<code> java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference
</code>```

I can't understand what's is my fault. Can you help me? Thank you

答: You are using the same fragment twice, and sending the argument once in basic only(setupviewpager and basic). Either pass the argument in both case or add a null check before getting the string.</p>

Body:
I want to pass a Serializable object from activity to fragment. But at fragment, getArguments() always retuns null. Then I try to pass a simple string value from activity to fragment, it still shows NullPointerExection.

Here is my Activity Class

public class FullProfile extends AppCompatActivity {
private Toolbar toolbar;
private TabLayout tabLayout;
private ViewPager viewPager;
private Customer customer;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_full_profile);

    tabLayout = findViewById(R.id.tabLayout);
    viewPager = findViewById(R.id.myViewPager);
    setupViewPager(viewPager);

    ProfileBasicFragment basic = new ProfileBasicFragment();
    Bundle bundle = new Bundle();
    bundle.putString("profile", "Hello Hello");

    basic.setArguments(bundle);
    getSupportFragmentManager().beginTransaction().add(R.id.myViewPager, basic).commit();

    tabLayout.setupWithViewPager(viewPager);

}

private void setupViewPager(ViewPager viewPager) {
    FragmentAdapter fragmentAdapter = new FragmentAdapter(getSupportFragmentManager(), 4);
    fragmentAdapter.addFragment(new ProfileBasicFragment(), "Profile");
    fragmentAdapter.addFragment(new ProductFragment(), "Product");
    fragmentAdapter.addFragment(new WatchListFragment(), "Choices");

    viewPager.setAdapter(fragmentAdapter);

}

}

Here is my Fragment..

public class ProfileBasicFragment extends Fragment {

TextView t;
String s;

public ProfileBasicFragment() {
    // Required empty public constructor
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_profile_basic, container, false);
    t = view.findViewById(R.id.nameTV);

    String s = getArguments().getString("profile");
    t.setText(s);

    return view;
}

}

And Here is the error

 java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference

I can't understand what's is my fault. Can you help me? Thank you


问:
Group the query into 3 columns, and display the sums for another column in Apex Oracle
I want to make a report. In my request it is not difficult. I specify dates and also type of record (positive or subtractive) in this request. I want this query to be grouped by fields CONTRACTORID, ITEMID ORGANIZATION. And withdraw the amount on the NETTO.</p>

```<code>select
  ID, DOCNUMBER,DOCDATE,PRINTNUMBER,DRIVERID,CONTRACTORID,ITEMID,
  BRUTTO,TARE,NETTO,
  DS_ID,
  DAT_A,
  MILEAGE,
  ORGANIZATION,
  sum(NETTO)
from WAYBILL
where trunc(DOCDATE) between to_date(:P115_D1,'dd.mm.yyyy')
                         and to_date(:P115_D2,'dd.mm.yyyy')
and DIRECTIONID = :P115_DIRECTIONID
group by
  ID, DOCNUMBER,DOCDATE,PRINTNUMBER,DRIVERID,CONTRACTORID,ITEMID,
  BRUTTO,TARE,NETTO,
  DS_ID,
  DAT_A,
  MILEAGE,
  ORGANIZATION
</code>```

答:
It seems you want to show the complete rows, each with the netto sum per its contractorid, itemid, and organization. You can achieve this with a window function:

```<code>select
  id,  docnumber, docdate, printnumber, driverid, contractorid, itemid,
  brutto, tare, netto, ds_id, dat_a, mileage, organization,
  sum(netto) over (partition by contractorid, itemid, organization) as netto_sum
from waybill
where trunc(docdate) between to_date(:p115_d1,'dd.mm.yyyy')
                         and to_date(:p115_d2,'dd.mm.yyyy')
and directionid = :p115_directionid
order by id;
</code>```

Body:
I want to make a report. In my request it is not difficult. I specify dates and also type of record (positive or subtractive) in this request. I want this query to be grouped by fields CONTRACTORID, ITEMID ORGANIZATION. And withdraw the amount on the NETTO.

select
  ID, DOCNUMBER,DOCDATE,PRINTNUMBER,DRIVERID,CONTRACTORID,ITEMID,
  BRUTTO,TARE,NETTO,
  DS_ID,
  DAT_A,
  MILEAGE,
  ORGANIZATION,
  sum(NETTO)
from WAYBILL
where trunc(DOCDATE) between to_date(:P115_D1,'dd.mm.yyyy')
                         and to_date(:P115_D2,'dd.mm.yyyy')
and DIRECTIONID = :P115_DIRECTIONID
group by
  ID, DOCNUMBER,DOCDATE,PRINTNUMBER,DRIVERID,CONTRACTORID,ITEMID,
  BRUTTO,TARE,NETTO,
  DS_ID,
  DAT_A,
  MILEAGE,
  ORGANIZATION

Body:
It seems you want to show the complete rows, each with the netto sum per its contractorid, itemid, and organization. You can achieve this with a window function:

select
  id,  docnumber, docdate, printnumber, driverid, contractorid, itemid,
  brutto, tare, netto, ds_id, dat_a, mileage, organization,
  sum(netto) over (partition by contractorid, itemid, organization) as netto_sum
from waybill
where trunc(docdate) between to_date(:p115_d1,'dd.mm.yyyy')
                         and to_date(:p115_d2,'dd.mm.yyyy')
and directionid = :p115_directionid
order by id;


问:
How to filter the div as we search in search box?
I made a page with 9 cards. The card is with the class name "card". I want to get the card when I type the letters. I want this to be filtered on the basis of p tag that consist "First project", "Second project" and so on for seven more.

function search() {
  let input = document.getElementById('.searchbar').value
  input = input.toLowerCase();
  let x = document.querySelector('.card p');

  for (i = 0; i < x.length; i++) {
    if (!x[i].innerHTML.toLowerCase().includes(input)) {
      x[i].style.display = "none";
    } else {
      x[i].style.display = "list-item";
    }
  }
}```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="main">

  <h3 class="first">Page Heading <span class="span-text">Secondary Text</span></h3>
  <form class='searchbox'>
    <input class="searchbar" type="text" onkeyup="search()" placeholder="Search.." name="search">
  </form>

  <section class="cards">
    <div class="card">
      <div class="card-box">700 x 400</div>
      <p style="color:blue; font-size:1.5rem;">First Project</p>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero quod non sed eveniet numquam perferendis.
      </p>
    </div>

    <div class="card">
      <div class="card-box">700 x 400</div>
      <p style="color:blue; font-size:1.5rem;">Second Project</p>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero quod non sed eveniet numquam perferendis.
      </p>
    </div>
    //and seven more of same "card" class
</div></code>```

I am not able to filter it when I type in the search box. Kindly guide on what is wrong and what I can do  to display the card that I searched.

答:
Change the line,

```<code>let input = document.getElementById('.searchbar').value
</code>```

To,

```<code>let input = document.querySelector('.searchbar').value
</code>```

-> Because using getElementById you can select the element with particular id but here you are using class and you cannot do like this..

But anyhow it is always the best practice to make function call in the
  javascript file with the help of addEventListener() and remove onkeyup="search()" in HTML template

-> Consider using nth selection option to select the first p element which is second element from card div like ('.card p:nth-child(2)'),

```<code>const x = document.querySelectorAll('.card p:nth-child(2)');
</code>```

Note that here you need to use querySelectorAll to get all the elements with the selection and this will return array of elements..

Working Snippet as follows,

const searchEl = document.querySelector('.searchbox');
const x = document.querySelectorAll('.card p:nth-child(2)');

function search(e){
  x.forEach((item,index) => {
    if(!item.innerHTML.toLowerCase().includes(e.target.value)){
      item.parentElement.style.display = 'none';
    }else {
      item.parentElement.style.display = 'block';
    }
  })
}

searchEl.addEventListener("keyup", search);   ```
<pre class="snippet-code-html lang-html prettyprint-override"><code><div class="main">

  <h3 class="first">Page Heading <span class="span-text">Secondary Text</span></h3>
  <form class='searchbox'>
    <input class="searchbar" type="text" placeholder="Search.." name="search">
  </form>

  <section class="cards">
    <div class="card">
      <div class="card-box">700 x 400</div>
      <p style="color:blue; font-size:1.5rem;">First Project</p>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero quod non sed eveniet numquam perferendis.
      </p>
    </div>

    <div class="card">
      <div class="card-box">700 x 400</div>
      <p style="color:blue; font-size:1.5rem;">Second Project</p>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero quod non sed eveniet numquam perferendis.
      </p>
    </div>
    //and seven more of same "card" class
</div></code>```

Body:
I made a page with 9 cards. The card is with the class name "card". I want to get the card when I type the letters. I want this to be filtered on the basis of p tag that consist "First project", "Second project" and so on for seven more.

function search() {
  let input = document.getElementById('.searchbar').value
  input = input.toLowerCase();
  let x = document.querySelector('.card p');

  for (i = 0; i < x.length; i++) {
    if (!x[i].innerHTML.toLowerCase().includes(input)) {
      x[i].style.display = "none";
    } else {
      x[i].style.display = "list-item";
    }
  }
}

Page Heading Secondary Text

  <form class='searchbox'>
    <input class="searchbar" type="text" onkeyup="search()" placeholder="Search.." name="search">
  </form>

700 x 400

First Project

        Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero quod non sed eveniet numquam perferendis.

700 x 400

Second Project

        Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero quod non sed eveniet numquam perferendis.

    //and seven more of same "card" class

I am not able to filter it when I type in the search box. Kindly guide on what is wrong and what I can do  to display the card that I searched.

Body:
Change the line,

let input = document.getElementById('.searchbar').value

To,

let input = document.querySelector('.searchbar').value

-> Because using getElementById you can select the element with particular id but here you are using class and you cannot do like this..

But anyhow it is always the best practice to make function call in the
  javascript file with the help of addEventListener() and remove onkeyup="search()" in HTML template

-> Consider using nth selection option to select the first p element which is second element from card div like ('.card p:nth-child(2)'),

const x = document.querySelectorAll('.card p:nth-child(2)');

Note that here you need to use querySelectorAll to get all the elements with the selection and this will return array of elements..

Working Snippet as follows,

const searchEl = document.querySelector('.searchbox');
const x = document.querySelectorAll('.card p:nth-child(2)');

function search(e){
  x.forEach((item,index) => {
    if(!item.innerHTML.toLowerCase().includes(e.target.value)){
      item.parentElement.style.display = 'none';
    }else {
      item.parentElement.style.display = 'block';
    }
  })
}

searchEl.addEventListener("keyup", search);

<div class="main">

  <h3 class="first">Page Heading <span class="span-text">Secondary Text</span></h3>
  <form class='searchbox'>
    <input class="searchbar" type="text" placeholder="Search.." name="search">
  </form>

  <section class="cards">
    <div class="card">
      <div class="card-box">700 x 400</div>
      <p style="color:blue; font-size:1.5rem;">First Project</p>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero quod non sed eveniet numquam perferendis.
      </p>
    </div>

    <div class="card">
      <div class="card-box">700 x 400</div>
      <p style="color:blue; font-size:1.5rem;">Second Project</p>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Libero quod non sed eveniet numquam perferendis.
      </p>
    </div>
    //and seven more of same "card" class
</div>


问:
Zend two submit buttons same name
I built a form class extending zend_form.I have two submitting buttons :

```<code>$like=new Zend_Form_Element_Image('vote');
$like->setImage($config->path->images."up.png")
->setValue(2);

$dislike=new Zend_Form_Element_Image('vote');
$dislike->setImage($config->path->images."down.png")
->setValue(1);
</code>```

I'd want to have two submit buttons with same name and different value so that I can later access the value of the submitted one  by a switch statement in the controller:

```<code>$submit = $this->_request->getPost('vote');

 switch($submit) {
 case 'one':
 // button one was pressed
 break;
 case 'two':
}

}
</code>```

But If I do set those with the same name the last one is overriding the first so only one button is output.

With file elements theres a method setMultifile() that does the trick.

what should I do here?

thanks

Luca

答: You might try using array notation for the images.</p>

Title: Zend two submit buttons same name

Body:
I built a form class extending zend_form.I have two submitting buttons :

$like=new Zend_Form_Element_Image('vote');
$like->setImage($config->path->images."up.png")
->setValue(2);

$dislike=new Zend_Form_Element_Image('vote');
$dislike->setImage($config->path->images."down.png")
->setValue(1);

I'd want to have two submit buttons with same name and different value so that I can later access the value of the submitted one  by a switch statement in the controller:

$submit = $this->_request->getPost('vote');

 switch($submit) {
 case 'one':
 // button one was pressed
 break;
 case 'two':
}

}

But If I do set those with the same name the last one is overriding the first so only one button is output.

With file elements theres a method setMultifile() that does the trick.

what should I do here?

thanks

Luca


问:
Build success but application error in Heroku
i'm trying to deploy my python app on heroku with the help of flask. I checked on the local machine it worked fine. When i deploy to the heroku build was success but when i open app it says application error
when I log the error with heroku logs --tail --app below is the error code.

```<code>2020-06-02T07:06:41.820850+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/mysql/connector/__init__.py", line 34, in <module>
2020-06-02T07:06:41.820850+00:00 app[web.1]: import _version
2020-06-02T07:06:41.820858+00:00 app[web.1]: ModuleNotFoundError: No module named '_version'
</code>```

my requirements.txt

```<code>mysql-connector==2.2.9
mysql-connector-python==8.0.20
mysql_connector_repackaged==0.3.1
mysqlclient==1.4.6
</code>```

can anyone help me?

答:
https://pypi.org/project/mysql-connector/

Support goes until Python 3.3. It also says in the description:

Deprecated, go for official version
  https://pypi.org/project/mysql-connector-python.

Remove the mysql-connector dependency.

Body:
i'm trying to deploy my python app on heroku with the help of flask. I checked on the local machine it worked fine. When i deploy to the heroku build was success but when i open app it says application error
when I log the error with heroku logs --tail --app below is the error code.

2020-06-02T07:06:41.820850+00:00 app[web.1]: File "/app/.heroku/python/lib/python3.6/site-packages/mysql/connector/__init__.py", line 34, in <module>
2020-06-02T07:06:41.820850+00:00 app[web.1]: import _version
2020-06-02T07:06:41.820858+00:00 app[web.1]: ModuleNotFoundError: No module named '_version'

my requirements.txt

mysql-connector==2.2.9
mysql-connector-python==8.0.20
mysql_connector_repackaged==0.3.1
mysqlclient==1.4.6

can anyone help me?


问:
JAVA_HOME path updated for version 11, java version in the cmd still showing 8
I had recently installed java 11 and set all the necessary paths in the system environment variables.

why does my java -version show the old java installed. Do i need to do something else to get his updated.

答:
I have noticed that older Java versions put a copy of java.exe and javaw.exe in a directory and reference it from there. That directory, I think, does not contain javac.exe so javac -version is fine but java -version is not fine.

So, java -version is still referring to old java.exe which is there somewhere in your file system.

Do "where java.exe" on command prompt to find where you have java.exe.

Then delete the older versions of java.exe and javaw.exe. Then try doing java -version again.


问:
Opening and Closing Tags are Removed from html When Using BeautifulSoup
I am running into an issue when using BeautifulSoup to scrape data off of www.basketball-reference.com. I've used BeautifulSoup before on Bballreference before so I am a little stumped as to what is happening (granted I am a pretty huge noob so please bear with me).

I am trying to scrape team season stats off of https://www.basketball-reference.com/leagues/NBA_2020.html and am running into troubles from the very start:

from bs4 import BeautifulSoup
import requests

web_response = requests.get('https://www.basketball-reference.com/leagues/NBA_2020.html').text
soup = BeautifulSoup(web_response, 'lxml')

table = soup.find('table', id='team-stats-per_game')
print(table)
```

<p>This shows that the finding of the table in question was unsuccessful even though I can clearly locate that tag when inspecting the web page. Okay... no biggie so far (usually these errors are on my end) so I instead just print out the whole soup:</p>

<pre class="lang-py prettyprint-override"><code>soup = BeautifulSoup(web_response, 'lxml')
print(soup)
</code>```

I copy and paste that into https://codebeautify.org/htmlviewer/. To get a better view than from the terminal and I see that it does not look how I would expect it to. Essentially the meta tags are fine but everything else appears to have lost its opening and closing tags, just making my soup into an actual soup...

Again, no biggie (still pretty sure it is something that I am doing), so I go and grab the html from a simple blog site, print it, and paste it into codebeautify and lo and behold it looks normal. Now I have a suspicion that something is occurring on basketball-reference's side that is obscuring my ability to even grab the html.

My question is this; what exactly is going on here? I am assuming it's an 80% chance it is still me but the 20% is not so sure at this point. Can someone point out what I am doing wrong or how to grab the html?

答:
The data is stored within the page, but inside the HTML comment.

To parse it, you can do for example:

```<code>import requests
from bs4 import BeautifulSoup, Comment

web_response = requests.get('https://www.basketball-reference.com/leagues/NBA_2020.html').text
soup = BeautifulSoup(web_response, 'lxml')

table = soup.find('table', id='team-stats-per_game')

# find the comment section where the data is stored
for idx, c in enumerate(soup.select_one('div#all_team-stats-per_game').contents):
    if isinstance(c, Comment):
        break

# load the data from comment:
soup2 = BeautifulSoup(soup.select_one('div#all_team-stats-per_game').contents[idx], 'html.parser')

# print data:
for tr in soup2.select('tr:has(td)'):
    tds = tr.select('td')
    for td in tds:
        print(td.get_text(strip=True), end='\t')
    print()
</code>```

Prints:

```<code>Dallas Mavericks    67  241.5   41.6    90.0    .462    15.3    41.5    .369    26.3    48.5    .542    17.9    23.1    .773    10.6    36.4    47.0    24.5    6.3 5.0 12.8    19.0    116.4
Milwaukee Bucks*    65  240.8   43.5    91.2    .477    13.7    38.6    .356    29.8    52.6    .567    17.8    24.0    .742    9.5 42.2    51.7    25.9    7.4 6.0 14.9    19.2    118.6
Houston Rockets 64  241.2   41.1    90.7    .454    15.4    44.3    .348    25.7    46.4    .554    20.5    26.0    .787    10.4    34.6    44.9    21.5    8.5 5.1 14.7    21.6    118.1
Portland Trail Blazers  66  240.8   41.9    90.9    .461    12.6    33.8    .372    29.3    57.1    .513    17.3    21.7    .798    10.1    35.4    45.5    20.2    6.1 6.2 13.0    21.4    113.6
Atlanta Hawks   67  243.0   40.6    90.6    .449    12.0    36.1    .333    28.6    54.5    .525    18.5    23.4    .790    9.9 33.4    43.3    24.0    7.8 5.1 16.2    23.1    111.8
New Orleans Pelicans    64  242.3   42.6    92.2    .462    14.0    37.6    .372    28.6    54.6    .525    16.9    23.2    .729    11.2    35.8    47.0    27.0    7.6 5.1 16.2    21.0    116.2
Los Angeles Clippers    64  241.2   41.6    89.7    .464    12.2    33.2    .366    29.5    56.5    .522    20.8    26.2    .792    11.0    37.0    48.0    23.8    7.1 5.0 14.8    22.0    116.2
Washington Wizards  64  241.2   41.9    91.0    .461    12.3    33.1    .372    29.6    57.9    .511    19.5    24.8    .787    10.1    31.6    41.7    25.3    8.1 4.3 14.1    22.6    115.6
Memphis Grizzlies   65  240.4   42.8    91.0    .470    10.9    31.1    .352    31.8    59.9    .531    16.2    21.3    .761    10.4    36.3    46.7    27.0    8.0 5.6 15.3    20.8    112.6
Phoenix Suns    65  241.2   40.8    87.8    .464    11.2    31.7    .353    29.6    56.1    .527    19.8    24.0    .826    9.8 33.3    43.1    27.2    7.8 4.0 15.1    22.1    112.6
Miami Heat  65  243.5   39.6    84.4    .470    13.4    34.8    .383    26.3    49.6    .530    19.5    25.1    .778    8.5 36.0    44.5    26.0    7.4 4.5 14.9    20.4    112.2
Minnesota Timberwolves  64  243.1   40.4    91.6    .441    13.3    39.7    .336    27.1    52.0    .521    19.1    25.4    .753    10.5    34.3    44.8    23.8    8.7 5.7 15.3    21.4    113.3
Boston Celtics* 64  242.0   41.2    89.6    .459    12.4    34.2    .363    28.8    55.4    .519    18.3    22.8    .801    10.7    35.3    46.0    22.8    8.3 5.6 13.6    21.4    113.0
Toronto Raptors*    64  241.6   40.6    88.5    .458    13.8    37.0    .371    26.8    51.5    .521    18.1    22.6    .800    9.7 35.5    45.2    25.4    8.8 4.9 14.4    21.5    113.0
Los Angeles Lakers* 63  240.8   42.9    88.6    .485    11.2    31.4    .355    31.8    57.1    .556    17.3    23.7    .730    10.6    35.5    46.1    25.9    8.6 6.8 15.1    20.6    114.3
Denver Nuggets  65  242.3   41.8    88.9    .471    10.9    30.4    .358    31.0    58.5    .529    15.9    20.5    .775    10.8    33.5    44.3    26.5    8.1 4.6 13.7    20.0    110.4
San Antonio Spurs   63  242.8   42.0    89.5    .470    10.7    28.7    .371    31.4    60.8    .517    18.4    22.8    .809    8.8 35.6    44.4    24.5    7.2 5.5 12.3    19.2    113.2
Philadelphia 76ers  65  241.2   40.8    87.7    .465    11.4    31.6    .362    29.4    56.1    .523    16.6    22.1    .752    10.4    35.1    45.5    25.9    8.2 5.4 14.2    20.6    109.6
Indiana Pacers  65  241.5   42.2    88.4    .477    10.0    27.5    .363    32.2    60.9    .529    15.1    19.1    .787    8.8 34.0    42.8    25.9    7.2 5.1 13.1    19.6    109.3
Utah Jazz   64  240.4   40.1    84.6    .475    13.2    34.4    .383    27.0    50.2    .537    17.6    22.8    .772    8.8 36.3    45.1    22.2    5.9 4.0 14.9    20.0    111.0
Oklahoma City Thunder   64  241.6   40.3    85.1    .473    10.4    29.3    .355    29.9    55.8    .536    19.8    24.8    .797    8.1 34.6    42.7    21.9    7.6 5.0 13.5    18.8    110.8
Brooklyn Nets   64  243.1   40.0    90.0    .444    12.9    37.9    .340    27.1    52.2    .519    18.0    24.1    .744    10.8    37.6    48.5    24.0    6.5 4.6 15.5    20.7    110.8
Detroit Pistons 66  241.9   39.3    85.7    .459    12.0    32.7    .367    27.3    53.0    .515    16.6    22.4    .743    9.8 32.0    41.7    24.1    7.4 4.5 15.3    19.7    107.2
New York Knicks 66  241.9   40.0    89.3    .447    9.6 28.4    .337    30.4    61.0    .499    16.3    23.5    .694    12.0    34.5    46.5    22.1    7.6 4.7 14.3    22.2    105.8
Sacramento Kings    64  242.3   40.4    87.8    .459    12.6    34.7    .364    27.7    53.2    .522    15.6    20.3    .769    9.6 32.9    42.5    23.4    7.6 4.2 14.4    21.9    109.0
Cleveland Cavaliers 65  241.9   40.3    87.9    .458    11.2    31.8    .351    29.1    56.1    .519    15.1    19.9    .758    10.8    33.4    44.2    23.1    6.9 3.2 16.5    18.3    106.9
Chicago Bulls   65  241.2   39.6    88.6    .447    12.2    35.1    .348    27.4    53.5    .511    15.5    20.5    .755    10.5    31.4    41.9    23.2    10.0    4.1 15.5    21.8    106.8
Orlando Magic   65  240.4   39.2    88.8    .442    10.9    32.0    .341    28.3    56.8    .498    17.0    22.1    .770    10.4    34.2    44.5    24.0    8.4 5.7 12.6    17.6    106.4
Golden State Warriors   65  241.9   38.6    88.2    .438    10.4    31.3    .334    28.2    56.9    .495    18.7    23.2    .803    10.0    32.9    42.8    25.6    8.2 4.6 14.9    20.1    106.3
Charlotte Hornets   65  242.3   37.3    85.9    .434    12.1    34.3    .352    25.2    51.6    .489    16.2    21.6    .748    11.0    31.8    42.8    23.8    6.6 4.1 14.6    18.8    102.9
League Average  65  241.7   40.8    88.8    .460    12.1    33.9    .357    28.7    54.9    .523    17.7    22.9    .771    10.1    34.7    44.9    24.3    7.7 4.9 14.5    20.6    111.4
</code>```

Body:
I am running into an issue when using BeautifulSoup to scrape data off of www.basketball-reference.com. I've used BeautifulSoup before on Bballreference before so I am a little stumped as to what is happening (granted I am a pretty huge noob so please bear with me).

I am trying to scrape team season stats off of https://www.basketball-reference.com/leagues/NBA_2020.html and am running into troubles from the very start:

from bs4 import BeautifulSoup
import requests

web_response = requests.get('https://www.basketball-reference.com/leagues/NBA_2020.html').text
soup = BeautifulSoup(web_response, 'lxml')

table = soup.find('table', id='team-stats-per_game')
print(table)

This shows that the finding of the table in question was unsuccessful even though I can clearly locate that tag when inspecting the web page. Okay... no biggie so far (usually these errors are on my end) so I instead just print out the whole soup:

soup = BeautifulSoup(web_response, 'lxml')
print(soup)

I copy and paste that into https://codebeautify.org/htmlviewer/. To get a better view than from the terminal and I see that it does not look how I would expect it to. Essentially the meta tags are fine but everything else appears to have lost its opening and closing tags, just making my soup into an actual soup...

Again, no biggie (still pretty sure it is something that I am doing), so I go and grab the html from a simple blog site, print it, and paste it into codebeautify and lo and behold it looks normal. Now I have a suspicion that something is occurring on basketball-reference's side that is obscuring my ability to even grab the html.

My question is this; what exactly is going on here? I am assuming it's an 80% chance it is still me but the 20% is not so sure at this point. Can someone point out what I am doing wrong or how to grab the html?

Body:
The data is stored within the page, but inside the HTML comment.

To parse it, you can do for example:

import requests
from bs4 import BeautifulSoup, Comment

web_response = requests.get('https://www.basketball-reference.com/leagues/NBA_2020.html').text
soup = BeautifulSoup(web_response, 'lxml')

table = soup.find('table', id='team-stats-per_game')

# find the comment section where the data is stored
for idx, c in enumerate(soup.select_one('div#all_team-stats-per_game').contents):
    if isinstance(c, Comment):
        break

# load the data from comment:
soup2 = BeautifulSoup(soup.select_one('div#all_team-stats-per_game').contents[idx], 'html.parser')

# print data:
for tr in soup2.select('tr:has(td)'):
    tds = tr.select('td')
    for td in tds:
        print(td.get_text(strip=True), end='\t')
    print()

Prints:

Dallas Mavericks    67  241.5   41.6    90.0    .462    15.3    41.5    .369    26.3    48.5    .542    17.9    23.1    .773    10.6    36.4    47.0    24.5    6.3 5.0 12.8    19.0    116.4
Milwaukee Bucks*    65  240.8   43.5    91.2    .477    13.7    38.6    .356    29.8    52.6    .567    17.8    24.0    .742    9.5 42.2    51.7    25.9    7.4 6.0 14.9    19.2    118.6
Houston Rockets 64  241.2   41.1    90.7    .454    15.4    44.3    .348    25.7    46.4    .554    20.5    26.0    .787    10.4    34.6    44.9    21.5    8.5 5.1 14.7    21.6    118.1
Portland Trail Blazers  66  240.8   41.9    90.9    .461    12.6    33.8    .372    29.3    57.1    .513    17.3    21.7    .798    10.1    35.4    45.5    20.2    6.1 6.2 13.0    21.4    113.6
Atlanta Hawks   67  243.0   40.6    90.6    .449    12.0    36.1    .333    28.6    54.5    .525    18.5    23.4    .790    9.9 33.4    43.3    24.0    7.8 5.1 16.2    23.1    111.8
New Orleans Pelicans    64  242.3   42.6    92.2    .462    14.0    37.6    .372    28.6    54.6    .525    16.9    23.2    .729    11.2    35.8    47.0    27.0    7.6 5.1 16.2    21.0    116.2
Los Angeles Clippers    64  241.2   41.6    89.7    .464    12.2    33.2    .366    29.5    56.5    .522    20.8    26.2    .792    11.0    37.0    48.0    23.8    7.1 5.0 14.8    22.0    116.2
Washington Wizards  64  241.2   41.9    91.0    .461    12.3    33.1    .372    29.6    57.9    .511    19.5    24.8    .787    10.1    31.6    41.7    25.3    8.1 4.3 14.1    22.6    115.6
Memphis Grizzlies   65  240.4   42.8    91.0    .470    10.9    31.1    .352    31.8    59.9    .531    16.2    21.3    .761    10.4    36.3    46.7    27.0    8.0 5.6 15.3    20.8    112.6
Phoenix Suns    65  241.2   40.8    87.8    .464    11.2    31.7    .353    29.6    56.1    .527    19.8    24.0    .826    9.8 33.3    43.1    27.2    7.8 4.0 15.1    22.1    112.6
Miami Heat  65  243.5   39.6    84.4    .470    13.4    34.8    .383    26.3    49.6    .530    19.5    25.1    .778    8.5 36.0    44.5    26.0    7.4 4.5 14.9    20.4    112.2
Minnesota Timberwolves  64  243.1   40.4    91.6    .441    13.3    39.7    .336    27.1    52.0    .521    19.1    25.4    .753    10.5    34.3    44.8    23.8    8.7 5.7 15.3    21.4    113.3
Boston Celtics* 64  242.0   41.2    89.6    .459    12.4    34.2    .363    28.8    55.4    .519    18.3    22.8    .801    10.7    35.3    46.0    22.8    8.3 5.6 13.6    21.4    113.0
Toronto Raptors*    64  241.6   40.6    88.5    .458    13.8    37.0    .371    26.8    51.5    .521    18.1    22.6    .800    9.7 35.5    45.2    25.4    8.8 4.9 14.4    21.5    113.0
Los Angeles Lakers* 63  240.8   42.9    88.6    .485    11.2    31.4    .355    31.8    57.1    .556    17.3    23.7    .730    10.6    35.5    46.1    25.9    8.6 6.8 15.1    20.6    114.3
Denver Nuggets  65  242.3   41.8    88.9    .471    10.9    30.4    .358    31.0    58.5    .529    15.9    20.5    .775    10.8    33.5    44.3    26.5    8.1 4.6 13.7    20.0    110.4
San Antonio Spurs   63  242.8   42.0    89.5    .470    10.7    28.7    .371    31.4    60.8    .517    18.4    22.8    .809    8.8 35.6    44.4    24.5    7.2 5.5 12.3    19.2    113.2
Philadelphia 76ers  65  241.2   40.8    87.7    .465    11.4    31.6    .362    29.4    56.1    .523    16.6    22.1    .752    10.4    35.1    45.5    25.9    8.2 5.4 14.2    20.6    109.6
Indiana Pacers  65  241.5   42.2    88.4    .477    10.0    27.5    .363    32.2    60.9    .529    15.1    19.1    .787    8.8 34.0    42.8    25.9    7.2 5.1 13.1    19.6    109.3
Utah Jazz   64  240.4   40.1    84.6    .475    13.2    34.4    .383    27.0    50.2    .537    17.6    22.8    .772    8.8 36.3    45.1    22.2    5.9 4.0 14.9    20.0    111.0
Oklahoma City Thunder   64  241.6   40.3    85.1    .473    10.4    29.3    .355    29.9    55.8    .536    19.8    24.8    .797    8.1 34.6    42.7    21.9    7.6 5.0 13.5    18.8    110.8
Brooklyn Nets   64  243.1   40.0    90.0    .444    12.9    37.9    .340    27.1    52.2    .519    18.0    24.1    .744    10.8    37.6    48.5    24.0    6.5 4.6 15.5    20.7    110.8
Detroit Pistons 66  241.9   39.3    85.7    .459    12.0    32.7    .367    27.3    53.0    .515    16.6    22.4    .743    9.8 32.0    41.7    24.1    7.4 4.5 15.3    19.7    107.2
New York Knicks 66  241.9   40.0    89.3    .447    9.6 28.4    .337    30.4    61.0    .499    16.3    23.5    .694    12.0    34.5    46.5    22.1    7.6 4.7 14.3    22.2    105.8
Sacramento Kings    64  242.3   40.4    87.8    .459    12.6    34.7    .364    27.7    53.2    .522    15.6    20.3    .769    9.6 32.9    42.5    23.4    7.6 4.2 14.4    21.9    109.0
Cleveland Cavaliers 65  241.9   40.3    87.9    .458    11.2    31.8    .351    29.1    56.1    .519    15.1    19.9    .758    10.8    33.4    44.2    23.1    6.9 3.2 16.5    18.3    106.9
Chicago Bulls   65  241.2   39.6    88.6    .447    12.2    35.1    .348    27.4    53.5    .511    15.5    20.5    .755    10.5    31.4    41.9    23.2    10.0    4.1 15.5    21.8    106.8
Orlando Magic   65  240.4   39.2    88.8    .442    10.9    32.0    .341    28.3    56.8    .498    17.0    22.1    .770    10.4    34.2    44.5    24.0    8.4 5.7 12.6    17.6    106.4
Golden State Warriors   65  241.9   38.6    88.2    .438    10.4    31.3    .334    28.2    56.9    .495    18.7    23.2    .803    10.0    32.9    42.8    25.6    8.2 4.6 14.9    20.1    106.3
Charlotte Hornets   65  242.3   37.3    85.9    .434    12.1    34.3    .352    25.2    51.6    .489    16.2    21.6    .748    11.0    31.8    42.8    23.8    6.6 4.1 14.6    18.8    102.9
League Average  65  241.7   40.8    88.8    .460    12.1    33.9    .357    28.7    54.9    .523    17.7    22.9    .771    10.1    34.7    44.9    24.3    7.7 4.9 14.5    20.6    111.4


问:
What is the meaning of $(Q)@: in Makefile
I've read in linux Makefile:

```<code>$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
    $(Q)@:
</code>```

What is the meaning of $(Q)@:?

I'm trying to google it, but google always crappy if the search using some weird character. So in the end i can't found any Manual about it.

答:
From the Make manual:

5.2 Recipe Echoing

Normally make prints each line of the recipe before it is executed. We call this echoing because it gives the appearance that you are typing the lines yourself.

When a line starts with ‘@’, the echoing of that line is suppressed. The ‘@’ is discarded before the line is passed to the shell. Typically you would use this for a command whose only effect is to print something, such as an echo command to indicate progress through the makefile:

```<code>@echo About to make distribution files
</code>```

When make is given the flag ‘-n’ or ‘--just-print’ it only echoes most recipes, without executing them. See Summary of Options. In this case even the recipe lines starting with ‘@’ are printed. This flag is useful for finding out which recipes make thinks are necessary without actually doing them.

The ‘-s’ or ‘--silent’ flag to make prevents all echoing, as if all recipes started with ‘@’. A rule in the makefile for the special target .SILENT without prerequisites has the same effect (see Special Built-in Target Names).

Body:
I've read in linux Makefile:

$(filter-out _all sub-make $(CURDIR)/Makefile, $(MAKECMDGOALS)) _all: sub-make
    $(Q)@:

What is the meaning of $(Q)@:?

I'm trying to google it, but google always crappy if the search using some weird character. So in the end i can't found any Manual about it.

Body:
From the Make manual:

5.2 Recipe Echoing

Normally make prints each line of the recipe before it is executed. We call this echoing because it gives the appearance that you are typing the lines yourself.

When a line starts with ‘@’, the echoing of that line is suppressed. The ‘@’ is discarded before the line is passed to the shell. Typically you would use this for a command whose only effect is to print something, such as an echo command to indicate progress through the makefile:

@echo About to make distribution files

When make is given the flag ‘-n’ or ‘--just-print’ it only echoes most recipes, without executing them. See Summary of Options. In this case even the recipe lines starting with ‘@’ are printed. This flag is useful for finding out which recipes make thinks are necessary without actually doing them.

The ‘-s’ or ‘--silent’ flag to make prevents all echoing, as if all recipes started with ‘@’. A rule in the makefile for the special target .SILENT without prerequisites has the same effect (see Special Built-in Target Names).


问:
If the constraints stop being met while the job is running, reschedule the job and show a Toast message saying that the job failed
I am playing with android JobService and in the process, I came along with the following challenge from Google codelabs:

Challenge: Up until now, your JobService tasks have simply delivered a notification, but JobScheduler is usually used for more robust background tasks, such as updating the weather or syncing with a database. Because background tasks can be more complex, programmatically and functionally, the job of notifying the framework when the task is complete falls on the developer. Fortunately, the developer can do this by calling jobFinished().

This challenge requires you to call jobFinished() after the task is complete:

Implement a JobService that starts an AsyncTask when the given

constraints are met.

The AsyncTask should sleep for 5 seconds.

If the    constraints stop being met while the thread is sleeping,
reschedule    the job and show a Toast message saying that the job
failed.

Well, I am struck at point number 3.

How can I determine whether the job constraints are still being met while the job is running?

Here is my code:

SyncActivity.kt

```<code>public fun scheduleSyncJob(view : View){
        val selectedNetworkID = networkOptionsSync.checkedRadioButtonId
        var selectedNetworkOption = JobInfo.NETWORK_TYPE_NONE
        when (selectedNetworkID) {
            R.id.noNetworkSync -> selectedNetworkOption = JobInfo.NETWORK_TYPE_NONE
            R.id.anyNetworkSync -> selectedNetworkOption = JobInfo.NETWORK_TYPE_ANY
            R.id.wifiNetworkSync -> selectedNetworkOption = JobInfo.NETWORK_TYPE_UNMETERED
        }

        val serviceName = ComponentName(packageName, AsynctaskJobService::class.java.name)
        val builder = JobInfo.Builder(JOB_ID, serviceName)
            .setRequiredNetworkType(selectedNetworkOption)
            .setRequiresCharging(chargingSwitchSync.isChecked())

        val constraintSet = ((selectedNetworkOption != JobInfo.NETWORK_TYPE_NONE) || chargingSwitchSync.isChecked)
        if (constraintSet) {
            val myJobInfo = builder.build()
            mScheduler?.schedule(myJobInfo)
            Toast.makeText(this, R.string.job_scheduled, Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this, R.string.no_constraint_toast, Toast.LENGTH_SHORT).show()
        }
    }
</code>```

As you can see, I am scheduling my job if, either any type of network connection is available or the device is charging.

And here is the AsynctaskJobService.kt

```<code>class AsynctaskJobService : JobService() {
    override fun onStopJob(params: JobParameters?): Boolean {
        TODO("Not yet implemented")
    }

    override fun onStartJob(jobParameters: JobParameters?): Boolean {
        JobTask(this).execute(jobParameters)
        return true
    }

    private class JobTask(private val jobService: JobService) :
        AsyncTask<JobParameters?, Void?, JobParameters>() {

        override fun doInBackground(vararg params: JobParameters?): JobParameters? {
            Log.d("Asynctask Running", System.currentTimeMillis().toString())
            SystemClock.sleep(5000)
            Log.d("Asynctask Running", System.currentTimeMillis().toString())
            return params[0]
        }

        override fun onPostExecute(jobParameters: JobParameters) {
            jobService.jobFinished(jobParameters, false)
            Toast.makeText(jobService, "Task Finished", Toast.LENGTH_SHORT).show();
        }
    }

}
</code>```

答:
I have tried this..

Main constraint for job is WIFI network only.
Whenever the constraint stop being met onStopJob callback method is called. hence i showed my message here.

You can try this.

Below is my job service(in java).

```<code>public class MyJobService extends JobService {
    private MyBackgroundTask myBackgroundTask;

    @Override
    public boolean onStartJob(final JobParameters params) {
        myBackgroundTask = new MyBackgroundTask();
        Log.e("Test", Thread.currentThread().getName());
        myBackgroundTask.execute(params);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        if (myBackgroundTask != null) {
            myBackgroundTask.cancel(true);
            Toast.makeText(getApplicationContext(), "Job Interrupted", Toast.LENGTH_SHORT).show();
        }
        return true;
    }

    class MyBackgroundTask extends AsyncTask<JobParameters, Void, Boolean> {

        private JobParameters parameters;

        @Override
        protected Boolean doInBackground(JobParameters... jobParameters) {
            try {
                parameters = jobParameters[0];
                Thread.sleep(5000);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            if (aBoolean) {
                Toast.makeText(getApplicationContext(), "Job Complete", Toast.LENGTH_SHORT).show();
            }
            jobFinished(parameters, !aBoolean);
        }
    }
}
</code>```

Body:
I am playing with android JobService and in the process, I came along with the following challenge from Google codelabs:

Challenge: Up until now, your JobService tasks have simply delivered a notification, but JobScheduler is usually used for more robust background tasks, such as updating the weather or syncing with a database. Because background tasks can be more complex, programmatically and functionally, the job of notifying the framework when the task is complete falls on the developer. Fortunately, the developer can do this by calling jobFinished().

This challenge requires you to call jobFinished() after the task is complete:

Implement a JobService that starts an AsyncTask when the given

constraints are met.

The AsyncTask should sleep for 5 seconds.

If the    constraints stop being met while the thread is sleeping,
reschedule    the job and show a Toast message saying that the job
failed.

Well, I am struck at point number 3.

How can I determine whether the job constraints are still being met while the job is running?

Here is my code:

SyncActivity.kt

public fun scheduleSyncJob(view : View){
        val selectedNetworkID = networkOptionsSync.checkedRadioButtonId
        var selectedNetworkOption = JobInfo.NETWORK_TYPE_NONE
        when (selectedNetworkID) {
            R.id.noNetworkSync -> selectedNetworkOption = JobInfo.NETWORK_TYPE_NONE
            R.id.anyNetworkSync -> selectedNetworkOption = JobInfo.NETWORK_TYPE_ANY
            R.id.wifiNetworkSync -> selectedNetworkOption = JobInfo.NETWORK_TYPE_UNMETERED
        }

        val serviceName = ComponentName(packageName, AsynctaskJobService::class.java.name)
        val builder = JobInfo.Builder(JOB_ID, serviceName)
            .setRequiredNetworkType(selectedNetworkOption)
            .setRequiresCharging(chargingSwitchSync.isChecked())

        val constraintSet = ((selectedNetworkOption != JobInfo.NETWORK_TYPE_NONE) || chargingSwitchSync.isChecked)
        if (constraintSet) {
            val myJobInfo = builder.build()
            mScheduler?.schedule(myJobInfo)
            Toast.makeText(this, R.string.job_scheduled, Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this, R.string.no_constraint_toast, Toast.LENGTH_SHORT).show()
        }
    }

As you can see, I am scheduling my job if, either any type of network connection is available or the device is charging.

And here is the AsynctaskJobService.kt

class AsynctaskJobService : JobService() {
    override fun onStopJob(params: JobParameters?): Boolean {
        TODO("Not yet implemented")
    }

    override fun onStartJob(jobParameters: JobParameters?): Boolean {
        JobTask(this).execute(jobParameters)
        return true
    }

    private class JobTask(private val jobService: JobService) :
        AsyncTask<JobParameters?, Void?, JobParameters>() {

        override fun doInBackground(vararg params: JobParameters?): JobParameters? {
            Log.d("Asynctask Running", System.currentTimeMillis().toString())
            SystemClock.sleep(5000)
            Log.d("Asynctask Running", System.currentTimeMillis().toString())
            return params[0]
        }

        override fun onPostExecute(jobParameters: JobParameters) {
            jobService.jobFinished(jobParameters, false)
            Toast.makeText(jobService, "Task Finished", Toast.LENGTH_SHORT).show();
        }
    }

}

Body:
I have tried this..

Main constraint for job is WIFI network only.
Whenever the constraint stop being met onStopJob callback method is called. hence i showed my message here.

You can try this.

Below is my job service(in java).

public class MyJobService extends JobService {
    private MyBackgroundTask myBackgroundTask;

    @Override
    public boolean onStartJob(final JobParameters params) {
        myBackgroundTask = new MyBackgroundTask();
        Log.e("Test", Thread.currentThread().getName());
        myBackgroundTask.execute(params);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        if (myBackgroundTask != null) {
            myBackgroundTask.cancel(true);
            Toast.makeText(getApplicationContext(), "Job Interrupted", Toast.LENGTH_SHORT).show();
        }
        return true;
    }

    class MyBackgroundTask extends AsyncTask<JobParameters, Void, Boolean> {

        private JobParameters parameters;

        @Override
        protected Boolean doInBackground(JobParameters... jobParameters) {
            try {
                parameters = jobParameters[0];
                Thread.sleep(5000);
                return true;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            if (aBoolean) {
                Toast.makeText(getApplicationContext(), "Job Complete", Toast.LENGTH_SHORT).show();
            }
            jobFinished(parameters, !aBoolean);
        }
    }
}